Eclipse SUMO - Simulation of Urban MObility
GNEGeometry.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
18 // File for geometry classes and functions
19 /****************************************************************************/
22 #include <utils/gui/div/GLHelper.h>
25 
26 #include "GNEGeometry.h"
27 #include "GNENet.h"
28 #include "GNEViewNet.h"
29 
30 #define CIRCLE_RESOLUTION (double)10 // inverse in degrees
31 
32 // ===========================================================================
33 // static member definitions
34 // ===========================================================================
36 
37 // ===========================================================================
38 // method definitions
39 // ===========================================================================
40 
41 // ---------------------------------------------------------------------------
42 // GNEGeometry::ExtremeGeometry - methods
43 // ---------------------------------------------------------------------------
44 
46  laneStartPosition(-1),
47  laneEndPosition(-1),
48  viewStartPos(Position::INVALID),
49  viewEndPos(Position::INVALID) {
50 }
51 
52 // ---------------------------------------------------------------------------
53 // GNEGeometry::Geometry - methods
54 // ---------------------------------------------------------------------------
55 
57  myLane(nullptr),
58  myAdditional(nullptr) {
59 }
60 
61 
63  myShape(shape),
64  myLane(nullptr),
65  myAdditional(nullptr) {
66  // calculate shape rotation and lenghts
68 }
69 
70 
71 GNEGeometry::Geometry::Geometry(const PositionVector& shape, const std::vector<double>& shapeRotations, const std::vector<double>& shapeLengths) :
72  myShape(shape),
73  myShapeRotations(shapeRotations),
74  myShapeLengths(shapeLengths),
75  myLane(nullptr),
76  myAdditional(nullptr) {
77 }
78 
79 
80 void
81 GNEGeometry::Geometry::updateGeometry(const PositionVector& shape, double startPos, double endPos,
82  const Position& extraFirstPosition, const Position& extraLastPosition) {
83  // first clear geometry
84  clearGeometry();
85  // set new shape
86  myShape = shape;
87  // check if we have to split the lane
88  if ((startPos != -1) || (endPos != -1)) {
89  // check if both start and end position must be swapped
90  if ((startPos != -1) && (endPos != -1) && (endPos < startPos)) {
91  std::swap(startPos, endPos);
92  }
93  // check that split positions are correct
94  if (startPos <= POSITION_EPS) {
95  if (endPos == -1) {
96  // leave shape unmodified
97  } else if (endPos <= POSITION_EPS) {
98  // use only first shape position
99  myShape = PositionVector({myShape.front()});
100  } else if (endPos < (shape.length() - POSITION_EPS)) {
101  // split shape using end position and use left part
102  myShape = myShape.splitAt(endPos).first;
103  }
104  } else if (startPos >= (shape.length() - POSITION_EPS)) {
105  // use only last position
106  myShape = PositionVector({myShape.back()});
107  } else if (endPos == -1) {
108  // split shape using start position and use the right part
109  myShape = myShape.splitAt(startPos).second;
110  } else if (endPos <= POSITION_EPS) {
111  // use only first shape position
112  myShape = PositionVector({myShape.front()});
113  } else if (endPos >= (shape.length() - POSITION_EPS)) {
114  // split shape using start position and use the right part
115  myShape = myShape.splitAt(startPos).second;
116  } else {
117  // split shape using start and end position
118  myShape = myShape.getSubpart(startPos, endPos);
119  }
120  }
121  // check if we have to add an extra first position
122  if (extraFirstPosition != Position::INVALID) {
123  myShape.push_front(extraFirstPosition);
124  }
125  // check if we have to add an extra last position
126  if (extraLastPosition != Position::INVALID) {
127  myShape.push_back(extraLastPosition);
128  }
129  // calculate shape rotation and lengths
130  calculateShapeRotationsAndLengths();
131 }
132 
133 
134 void
135 GNEGeometry::Geometry::updateGeometry(const Position& position, const double rotation) {
136  // first clear geometry
137  clearGeometry();
138  // set position and rotation
139  myShape.push_back(position);
140  myShapeRotations.push_back(rotation);
141 }
142 
143 
144 void
145 GNEGeometry::Geometry::updateGeometry(const GNELane* lane, const double posOverLane) {
146  // first clear geometry
147  clearGeometry();
148  // get lane length
149  const double laneLength = lane->getLaneShape().length();
150  // calculate position and rotation
151  if (posOverLane < 0) {
152  myShape.push_back(lane->getLaneShape().positionAtOffset(0));
153  myShapeRotations.push_back(lane->getLaneShape().rotationDegreeAtOffset(0));
154  } else if (posOverLane > laneLength) {
155  myShape.push_back(lane->getLaneShape().positionAtOffset(laneLength));
156  myShapeRotations.push_back(lane->getLaneShape().rotationDegreeAtOffset(laneLength));
157  } else {
158  myShape.push_back(lane->getLaneShape().positionAtOffset(posOverLane));
159  myShapeRotations.push_back(lane->getLaneShape().rotationDegreeAtOffset(posOverLane));
160  }
161 }
162 
163 
164 void
166  // first clear geometry
167  clearGeometry();
168  // set lane
169  myLane = lane;
170 }
171 
172 
173 void
175  // first clear geometry
176  clearGeometry();
177  // set additional
178  myAdditional = additional;
179 }
180 
181 
182 void
184  // first clear geometry
185  clearGeometry();
186  // set geometry
187  myShape = geometry.getShape();
188  myShapeRotations = geometry.getShapeRotations();
189  myShapeLengths = geometry.getShapeLengths();
190 }
191 
192 
193 void
195  // scale shape and lenghts
196  myShape.scaleRelative(scale);
197  // scale lenghts
198  for (auto& shapeLength : myShapeLengths) {
199  shapeLength *= scale;
200  }
201 }
202 
203 
204 const PositionVector&
206  if (myLane) {
207  return myLane->getLaneShape();
208  } else if (myAdditional) {
209  return myAdditional->getAdditionalGeometry().getShape();
210  } else {
211  return myShape;
212  }
213 }
214 
215 
216 const std::vector<double>&
218  if (myLane) {
219  return myLane->getShapeRotations();
220  } else if (myAdditional) {
221  return myAdditional->getAdditionalGeometry().getShapeRotations();
222  } else {
223  return myShapeRotations;
224  }
225 }
226 
227 
228 const std::vector<double>&
230  if (myLane) {
231  return myLane->getShapeLengths();
232  } else if (myAdditional) {
233  return myAdditional->getAdditionalGeometry().getShapeLengths();
234  } else {
235  return myShapeLengths;
236  }
237 }
238 
239 
241  // clear shapes
242  myShape.clear();
243  myShapeRotations.clear();
244  myShapeLengths.clear();
245  // clear pointers
246  myLane = nullptr;
247  myAdditional = nullptr;
248 }
249 
250 
251 void
253  // clear rotations and lengths
254  myShapeRotations.clear();
255  myShapeLengths.clear();
256  // Get number of parts of the shape
257  int numberOfSegments = (int)myShape.size() - 1;
258  // If number of segments is more than 0
259  if (numberOfSegments >= 0) {
260  // Reserve memory (To improve efficiency)
261  myShapeRotations.reserve(numberOfSegments);
262  myShapeLengths.reserve(numberOfSegments);
263  // Calculate lengths and rotations for every shape
264  for (int i = 0; i < numberOfSegments; i++) {
265  myShapeRotations.push_back(calculateRotation(myShape[i], myShape[i + 1]));
266  myShapeLengths.push_back(calculateLength(myShape[i], myShape[i + 1]));
267  }
268  }
269 }
270 
271 // ---------------------------------------------------------------------------
272 // GNEGeometry::DottedGeometryColor - methods
273 // ---------------------------------------------------------------------------
274 
276  mySettings(settings),
277  myColorFlag(true) {}
278 
279 
280 const RGBColor&
282  if (myColorFlag) {
283  myColorFlag = false;
284  return mySettings.dottedContourSettings.firstInspectedColor;
285  } else {
286  myColorFlag = true;
287  return mySettings.dottedContourSettings.secondInspectedColor;
288  }
289 }
290 
291 
292 const RGBColor&
294  if (myColorFlag) {
295  myColorFlag = false;
296  return mySettings.dottedContourSettings.firstFrontColor;
297  } else {
298  myColorFlag = true;
299  return mySettings.dottedContourSettings.secondFrontColor;
300  }
301 }
302 
303 
304 void
306  if (myColorFlag) {
307  myColorFlag = false;
308  } else {
309  myColorFlag = true;
310  }
311 }
312 
313 
314 void
316  myColorFlag = true;
317 }
318 
319 // ---------------------------------------------------------------------------
320 // GNEGeometry::DottedGeometry - methods
321 // ---------------------------------------------------------------------------
322 
323 
325  offset(-1) {
326 }
327 
328 
330  shape(newShape),
331  offset(-1) {
332 }
333 
334 
336  myWidth(0) {
337 }
338 
339 
340 #if defined(_MSC_VER) && _MSC_VER == 1800
341 #pragma warning(push)
342 #pragma warning(disable: 4100) // do not warn about "unused" parameters which get optimized away
343 #endif
345  myWidth(s.dottedContourSettings.segmentWidth) {
346  // check if shape has to be closed
347  if (closeShape && (shape.size() > 2)) {
348  shape.closePolygon();
349  }
350  if (shape.size() > 1) {
351  // get shape
352  for (int i = 1; i < (int)shape.size(); i++) {
353  myDottedGeometrySegments.push_back(Segment({shape[i - 1], shape[i]}));
354  }
355  // resample
356  for (auto& segment : myDottedGeometrySegments) {
357  segment.shape = segment.shape.resample(s.dottedContourSettings.segmentLength, true);
358  }
359  // calculate shape rotations and lenghts
361  }
362 }
363 
364 
366  const DottedGeometry& topDottedGeometry, const bool drawFirstExtrem,
367  const DottedGeometry& botDottedGeometry, const bool drawLastExtrem) :
368  myWidth(s.dottedContourSettings.segmentWidth) {
369  // check size of both geometries
370  if ((topDottedGeometry.myDottedGeometrySegments.size() > 0) &&
371  (botDottedGeometry.myDottedGeometrySegments.size() > 0)) {
372  // add extremes
373  if (drawFirstExtrem &&
374  (topDottedGeometry.myDottedGeometrySegments.front().shape.size() > 0) &&
375  (botDottedGeometry.myDottedGeometrySegments.front().shape.size() > 0)) {
376  // add first extreme
378  topDottedGeometry.myDottedGeometrySegments.front().shape.front(),
379  botDottedGeometry.myDottedGeometrySegments.front().shape.front()}));
380  }
381  if (drawLastExtrem &&
382  (topDottedGeometry.myDottedGeometrySegments.back().shape.size() > 0) &&
383  (botDottedGeometry.myDottedGeometrySegments.back().shape.size() > 0)) {
384  // add last extreme
386  topDottedGeometry.myDottedGeometrySegments.back().shape.back(),
387  botDottedGeometry.myDottedGeometrySegments.back().shape.back()}));
388  // invert offset of second dotted geometry
389  myDottedGeometrySegments.back().offset *= -1;
390  }
391  }
392  // resample
393  for (auto& segment : myDottedGeometrySegments) {
394  segment.shape = segment.shape.resample(s.dottedContourSettings.segmentLength, true);
395  }
396  // calculate shape rotations and lenghts
398 }
399 
400 
401 void
403  // update settings and width
405  // reset segments
406  myDottedGeometrySegments.clear();
407  // get shape
408  for (int i = 1; i < (int)lane->getLaneShape().size(); i++) {
409  myDottedGeometrySegments.push_back(Segment({lane->getLaneShape()[i - 1], lane->getLaneShape()[i]}));
410  }
411  // resample
412  for (auto& segment : myDottedGeometrySegments) {
413  segment.shape = segment.shape.resample(s.dottedContourSettings.segmentLength, true);
414  }
415  // calculate shape rotations and lenghts
416  calculateShapeRotationsAndLengths();
417 }
418 
419 
420 void
422  // update settings and width
424  // reset segments
425  myDottedGeometrySegments.clear();
426  // check if shape has to be closed
427  if (closeShape && (shape.size() > 2)) {
428  shape.closePolygon();
429  }
430  if (shape.size() > 1) {
431  // get shape
432  for (int i = 1; i < (int)shape.size(); i++) {
433  myDottedGeometrySegments.push_back(Segment({shape[i - 1], shape[i]}));
434  }
435  // resample
436  for (auto& segment : myDottedGeometrySegments) {
437  segment.shape = segment.shape.resample(s.dottedContourSettings.segmentLength, true);
438  }
439  // calculate shape rotations and lenghts
440  calculateShapeRotationsAndLengths();
441  }
442 }
443 #if defined(_MSC_VER) && _MSC_VER == 1800
444 #pragma warning(pop)
445 #endif
446 
447 
448 void
450  // iterate over all segments
451  for (auto& segment : myDottedGeometrySegments) {
452  // iterate over shape
453  for (int i = 0; i < ((int)segment.shape.size() - 1); i++) {
454  // set color
455  GLHelper::setColor(dottedGeometryColor.getInspectedColor());
456  // draw box line
457  GLHelper::drawBoxLine(segment.shape[i],
458  segment.rotations.at(i),
459  segment.lengths.at(i),
460  myWidth, myWidth * segment.offset);
461  }
462  }
463 }
464 
465 
466 void
468  // iterate over all segments
469  for (auto& segment : myDottedGeometrySegments) {
470  // iterate over shape
471  for (int i = 0; i < ((int)segment.shape.size() - 1); i++) {
472  // set color
473  GLHelper::setColor(dottedGeometryColor.getFrontColor());
474  // draw box line
475  GLHelper::drawBoxLine(segment.shape[i],
476  segment.rotations.at(i),
477  segment.lengths.at(i),
478  myWidth, myWidth * segment.offset);
479  }
480  }
481 }
482 
483 
484 void
486  // move 2 side
487  for (auto& segment : myDottedGeometrySegments) {
488  segment.shape.move2side(value);
489  }
490 }
491 
492 
493 double
495  return myWidth;
496 }
497 
498 
499 void
501  myWidth = width;
502 }
503 
504 
505 void
507  // iterate over all segments
508  for (auto& segment : myDottedGeometrySegments) {
509  segment.offset *= -1;
510  }
511 }
512 
513 
514 void
516  // iterate over all segments
517  for (auto& segment : myDottedGeometrySegments) {
518  // Get number of parts of the shape
519  int numberOfSegments = (int)segment.shape.size() - 1;
520  // If number of segments is more than 0
521  if (numberOfSegments >= 0) {
522  // Reserve memory (To improve efficiency)
523  segment.rotations.reserve(numberOfSegments);
524  segment.lengths.reserve(numberOfSegments);
525  // Calculate lengths and rotations for every shape
526  for (int i = 0; i < numberOfSegments; i++) {
527  segment.rotations.push_back(calculateRotation(segment.shape[i], segment.shape[i + 1]));
528  segment.lengths.push_back(calculateLength(segment.shape[i], segment.shape[i + 1]));
529  }
530  }
531  }
532 }
533 
534 // ---------------------------------------------------------------------------
535 // GNEGeometry::SegmentGeometry::Segment - methods
536 // ---------------------------------------------------------------------------
537 
539  myLane(lane),
540  myNextLane(nullptr),
541  myValid(valid),
542  myUseLaneShape(true) {
543 }
544 
545 
546 GNEGeometry::SegmentGeometry::Segment::Segment(const GNELane* lane, const Geometry& geometry, const bool valid) :
547  myLane(lane),
548  myNextLane(nullptr),
549  myValid(valid),
550  myUseLaneShape(false),
551  mySegmentGeometry(geometry) {
552 }
553 
554 
555 GNEGeometry::SegmentGeometry::Segment::Segment(const GNELane* lane, const GNELane* nextLane, const bool valid) :
556  myLane(lane),
557  myNextLane(nextLane),
558  myValid(valid),
559  myUseLaneShape(false) {
560 }
561 
562 
563 void
565  // disable use lane shape
566  myUseLaneShape = false;
567  // update geometry
568  mySegmentGeometry.updateGeometry(geometry);
569 }
570 
571 
572 void
574  // enable use lane shape
575  myUseLaneShape = true;
576  // update geometry
577  mySegmentGeometry.updateGeometry(lane);
578 }
579 
580 
581 const PositionVector&
583  if (myNextLane) {
584  return myLane->getLane2laneConnections().getLane2laneGeometry(myNextLane).getShape();
585  } else if (myUseLaneShape) {
586  return myLane->getLaneShape();
587  } else {
588  return mySegmentGeometry.getShape();
589  }
590 }
591 
592 
593 const std::vector<double>&
595  if (myNextLane) {
596  return myLane->getLane2laneConnections().getLane2laneGeometry(myNextLane).getShapeRotations();
597  } else if (myUseLaneShape) {
598  return myLane->getShapeRotations();
599  } else {
600  return mySegmentGeometry.getShapeRotations();
601  }
602 }
603 
604 
605 const std::vector<double>&
607  if (myNextLane) {
608  return myLane->getLane2laneConnections().getLane2laneGeometry(myNextLane).getShapeLengths();
609  } else if (myUseLaneShape) {
610  return myLane->getShapeLengths();
611  } else {
612  return mySegmentGeometry.getShapeLengths();
613  }
614 }
615 
616 
617 const GNELane*
619  return myLane;
620 }
621 
622 
623 const GNEJunction*
625  return myLane->getParentEdge()->getParentJunctions().back();
626 }
627 
628 
629 bool
631  return myValid;
632 }
633 
634 
635 bool
637  return (myNextLane == nullptr);
638 }
639 
640 // ---------------------------------------------------------------------------
641 // GNEGeometry::SegmentGeometry::SegmentToUpdate - methods
642 // ---------------------------------------------------------------------------
643 
644 GNEGeometry::SegmentGeometry::SegmentToUpdate::SegmentToUpdate(const int segmentIndex, const GNELane* lane, const GNELane* nextLane) :
645  mySegmentIndex(segmentIndex),
646  myLane(lane),
647  myNextLane(nextLane) {
648 }
649 
650 
651 int
653  return mySegmentIndex;
654 }
655 
656 
657 const GNELane*
659  return myLane;
660 }
661 
662 
663 const GNELane*
665  return myNextLane;
666 }
667 
668 // ---------------------------------------------------------------------------
669 // GNEGeometry::Geometry - methods
670 // ---------------------------------------------------------------------------
671 
673 
674 
675 void
677  // add segment in myShapeSegments
678  myShapeSegments.push_back(Segment(lane, valid));
679 }
680 
681 
682 void
683 GNEGeometry::SegmentGeometry::insertCustomSegment(const GNELane* lane, const Geometry& geometry, const bool valid) {
684  // add segment in myShapeSegments
685  myShapeSegments.push_back(Segment(lane, geometry, valid));
686 }
687 
688 
689 void
690 GNEGeometry::SegmentGeometry::insertLane2LaneSegment(const GNELane* currentLane, const GNELane* nextLane, const bool valid) {
691  // add segment in myShapeSegments
692  myShapeSegments.push_back(Segment(currentLane, nextLane, valid));
693 }
694 
695 
696 void
697 GNEGeometry::SegmentGeometry::updateCustomSegment(const int segmentIndex, const Geometry& geometry) {
698  myShapeSegments.at(segmentIndex).update(geometry);
699 }
700 
701 
702 void
703 GNEGeometry::SegmentGeometry::updateLane2LaneSegment(const int segmentIndex, const GNELane* lane, const GNELane* nextLane) {
704  myShapeSegments.at(segmentIndex + 1).update(lane->getLane2laneConnections().getLane2laneGeometry(nextLane));
705 }
706 
707 
708 void
710  // clear segments
711  myShapeSegments.clear();
712 }
713 
714 
715 const Position&
717  if ((myShapeSegments.size() > 0) && (myShapeSegments.front().getShape().size() > 0)) {
718  return myShapeSegments.front().getShape().front();
719  } else {
720  return Position::INVALID;
721  }
722 }
723 
724 const Position&
726  if ((myShapeSegments.size() > 0) && (myShapeSegments.back().getShape().size() > 0)) {
727  return myShapeSegments.back().getShape().back();
728  } else {
729  return Position::INVALID;
730  }
731 }
732 
733 
734 double
736  if ((myShapeSegments.size() > 0) && (myShapeSegments.front().getShapeRotations().size() > 0)) {
737  return myShapeSegments.front().getShapeRotations().front();
738  } else {
739  return 0;
740  }
741 }
742 
743 
744 Boundary
746  Boundary b;
747  for (const auto& i : myShapeSegments) {
748  b.add(i.getShape().getBoxBoundary());
749  }
750  return b;
751 }
752 
753 
754 std::vector<GNEGeometry::SegmentGeometry::Segment>::const_iterator
756  return myShapeSegments.cbegin();
757 }
758 
759 
760 std::vector<GNEGeometry::SegmentGeometry::Segment>::const_iterator
762  return myShapeSegments.cend();
763 }
764 
765 
768  return myShapeSegments.front();
769 }
770 
771 
774  return myShapeSegments.back();
775 }
776 
777 
778 int
780  return (int)myShapeSegments.size();
781 }
782 
783 // ---------------------------------------------------------------------------
784 // GNEGeometry::Lane2laneConnection - methods
785 // ---------------------------------------------------------------------------
786 
788  myFromLane(fromLane) {
789 }
790 
791 
792 void
794  // declare numPoints
795  const int numPoints = 5;
796  const int maximumLanes = 10;
797  // clear connectionsMap
798  myConnectionsMap.clear();
799  // iterate over outgoingEdge's lanes
800  for (const auto& outgoingEdge : myFromLane->getParentEdge()->getParentJunctions().back()->getGNEOutgoingEdges()) {
801  for (const auto& outgoingLane : outgoingEdge->getLanes()) {
802  // get NBEdges from and to
803  const NBEdge* NBEdgeFrom = myFromLane->getParentEdge()->getNBEdge();
804  const NBEdge* NBEdgeTo = outgoingLane->getParentEdge()->getNBEdge();
805  // declare shape
806  PositionVector shape;
807  // only create smooth shapes if Edge From has as maximum 10 lanes
808  if ((NBEdgeFrom->getNumLanes() <= maximumLanes) && (NBEdgeFrom->getToNode()->getShape().area() > 4)) {
809  // calculate smoot shape
810  shape = NBEdgeFrom->getToNode()->computeSmoothShape(
811  NBEdgeFrom->getLaneShape(myFromLane->getIndex()),
812  NBEdgeTo->getLaneShape(outgoingLane->getIndex()),
813  numPoints, NBEdgeFrom->getTurnDestination() == NBEdgeTo,
814  (double) numPoints * (double) NBEdgeFrom->getNumLanes(),
815  (double) numPoints * (double) NBEdgeTo->getNumLanes());
816  } else {
817  // create a shape using lane shape extremes
818  shape = {myFromLane->getLaneShape().back(), outgoingLane->getLaneShape().front()};
819  }
820  // update connection map
821  myConnectionsMap[outgoingLane].first.updateGeometry(shape);
822  if (myFromLane->getNet()->getViewNet()) {
823  myConnectionsMap[outgoingLane].second.updateDottedGeometry(myFromLane->getNet()->getViewNet()->getVisualisationSettings(), shape, false);
824  }
825  }
826  }
827 }
828 
829 
830 bool
832  return (myConnectionsMap.count(toLane) > 0);
833 }
834 
835 
838  return myConnectionsMap.at(toLane).first;
839 }
840 
841 
844  return myConnectionsMap.at(toLane).second;
845 }
846 
847 
849  myFromLane(nullptr) {
850 }
851 
852 // ---------------------------------------------------------------------------
853 // GNEGeometry::HierarchicalConnections - methods
854 // ---------------------------------------------------------------------------
855 
857  myLane(lane),
858  myRotation(0) {
859  // set position and length depending of shape's lengt
860  if (lane->getLaneShape().length() - 6 > 0) {
863  } else {
866  }
867 }
868 
869 
870 const GNELane*
872  return myLane;
873 }
874 
875 
876 const Position&
878  return myPosition;
879 }
880 
881 
882 double
884  return myRotation;
885 }
886 
887 
889  myLane(nullptr),
890  myRotation(0) {
891 }
892 
893 
895  myHierarchicalElement(hierarchicalElement) {}
896 
897 
898 void
900  // first clear containers
901  connectionsGeometries.clear();
902  symbolsPositionAndRotation.clear();
903  // calculate position and rotation of every simbol for every edge
904  for (const auto& edge : myHierarchicalElement->getChildEdges()) {
905  for (const auto& lane : edge->getLanes()) {
906  symbolsPositionAndRotation.push_back(ConnectionGeometry(lane));
907  }
908  }
909  // calculate position and rotation of every symbol for every lane
910  for (const auto& lane : myHierarchicalElement->getChildLanes()) {
911  symbolsPositionAndRotation.push_back(ConnectionGeometry(lane));
912  }
913  // calculate position for every child additional
914  for (const auto& additional : myHierarchicalElement->getChildAdditionals()) {
915  // check that additional position is different of parent position
916  if (additional->getPositionInView() != myHierarchicalElement->getPositionInView()) {
917  // create connection shape
918  std::vector<Position> connectionShape;
919  const double A = std::abs(additional->getPositionInView().x() - myHierarchicalElement->getPositionInView().x());
920  const double B = std::abs(additional->getPositionInView().y() - myHierarchicalElement->getPositionInView().y());
921  // Set positions of connection's vertex. Connection is build from Entry to E3
922  connectionShape.push_back(additional->getPositionInView());
923  if (myHierarchicalElement->getPositionInView().x() > additional->getPositionInView().x()) {
924  if (myHierarchicalElement->getPositionInView().y() > additional->getPositionInView().y()) {
925  connectionShape.push_back(Position(additional->getPositionInView().x() + A, additional->getPositionInView().y()));
926  } else {
927  connectionShape.push_back(Position(additional->getPositionInView().x(), additional->getPositionInView().y() - B));
928  }
929  } else {
930  if (myHierarchicalElement->getPositionInView().y() > additional->getPositionInView().y()) {
931  connectionShape.push_back(Position(additional->getPositionInView().x(), additional->getPositionInView().y() + B));
932  } else {
933  connectionShape.push_back(Position(additional->getPositionInView().x() - A, additional->getPositionInView().y()));
934  }
935  }
936  connectionShape.push_back(myHierarchicalElement->getPositionInView());
937  // declare Geometry
938  GNEGeometry::Geometry geometry;
939  // update geometry with connectino shape
940  geometry.updateGeometry(connectionShape);
941  // add geometry in connectionsGeometry
942  connectionsGeometries.push_back(geometry);
943  }
944  }
945  // calculate geometry for connections between parent and children
946  for (const auto& symbol : symbolsPositionAndRotation) {
947  // create connection shape
948  std::vector<Position> connectionShape;
949  const double A = std::abs(symbol.getPosition().x() - myHierarchicalElement->getPositionInView().x());
950  const double B = std::abs(symbol.getPosition().y() - myHierarchicalElement->getPositionInView().y());
951  // Set positions of connection's vertex. Connection is build from Entry to E3
952  connectionShape.push_back(symbol.getPosition());
953  if (myHierarchicalElement->getPositionInView().x() > symbol.getPosition().x()) {
954  if (myHierarchicalElement->getPositionInView().y() > symbol.getPosition().y()) {
955  connectionShape.push_back(Position(symbol.getPosition().x() + A, symbol.getPosition().y()));
956  } else {
957  connectionShape.push_back(Position(symbol.getPosition().x(), symbol.getPosition().y() - B));
958  }
959  } else {
960  if (myHierarchicalElement->getPositionInView().y() > symbol.getPosition().y()) {
961  connectionShape.push_back(Position(symbol.getPosition().x(), symbol.getPosition().y() + B));
962  } else {
963  connectionShape.push_back(Position(symbol.getPosition().x() - A, symbol.getPosition().y()));
964  }
965  }
966  connectionShape.push_back(myHierarchicalElement->getPositionInView());
967  // declare Geometry
968  GNEGeometry::Geometry geometry;
969  // update geometry with connectino shape
970  geometry.updateGeometry(connectionShape);
971  // add geometry in connectionsGeometry
972  connectionsGeometries.push_back(geometry);
973  }
974 }
975 
976 
977 void
979  // Iterate over myConnectionPositions
980  for (const auto& connectionGeometry : connectionsGeometries) {
981  // Add a draw matrix
982  glPushMatrix();
983  // Set color
984  if (AC->isAttributeCarrierSelected()) {
986  } else {
988  }
989  // Draw box lines
990  GLHelper::drawBoxLines(connectionGeometry.getShape(), connectionGeometry.getShapeRotations(), connectionGeometry.getShapeLengths(), exaggeration * 0.1);
991  // Pop draw matrix
992  glPopMatrix();
993  }
994 }
995 
996 
997 void
999  // Iterate over myConnectionPositions
1000  for (const auto& connectionGeometry : connectionsGeometries) {
1001  // calculate dotted geometry
1002  GNEGeometry::DottedGeometry dottedGeometry(s, connectionGeometry.getShape(), false);
1003  // Add a draw matrix
1004  glPushMatrix();
1005  // traslate back
1006  if (type == DottedContourType::INSPECT) {
1007  glTranslated(0, 0, (-1 * GLO_DOTTEDCONTOUR_INSPECTED) - 0.01);
1008  } else if (type == DottedContourType::FRONT) {
1009  glTranslated(0, 0, (-1 * GLO_DOTTEDCONTOUR_FRONT) - 0.01);
1010  }
1011  // change default width
1012  dottedGeometry.setWidth(0.1);
1013  // use drawDottedContourLane to draw it
1014  GNEGeometry::drawDottedContourLane(type, s, dottedGeometry, exaggeration * 0.1, false, false);
1015  // Pop draw matrix
1016  glPopMatrix();
1017  }
1018 }
1019 
1020 // ---------------------------------------------------------------------------
1021 // GNEGeometry - methods
1022 // ---------------------------------------------------------------------------
1023 
1024 double
1025 GNEGeometry::calculateRotation(const Position& first, const Position& second) {
1026  // return rotation (angle) of the vector constructed by points first and second
1027  return ((double)atan2((second.x() - first.x()), (first.y() - second.y())) * (double) 180.0 / (double)M_PI);
1028 }
1029 
1030 
1031 double
1032 GNEGeometry::calculateLength(const Position& first, const Position& second) {
1033  // return 2D distance between two points
1034  return first.distanceTo2D(second);
1035 }
1036 
1037 
1038 void
1039 GNEGeometry::adjustStartPosGeometricPath(double& startPos, const GNELane* startLane, double& endPos, const GNELane* endLane) {
1040  // adjust both, if start and end lane are the same
1041  if (startLane && endLane && (startLane == endLane) && (startPos != -1) && (endPos != -1)) {
1042  if (startPos >= endPos) {
1043  endPos = (startPos + POSITION_EPS);
1044  }
1045  }
1046  // adjust startPos
1047  if ((startPos != -1) && startLane) {
1048  if (startPos < POSITION_EPS) {
1049  startPos = POSITION_EPS;
1050  }
1051  if (startPos > (startLane->getLaneShape().length() - POSITION_EPS)) {
1052  startPos = (startLane->getLaneShape().length() - POSITION_EPS);
1053  }
1054  }
1055  // adjust endPos
1056  if ((endPos != -1) && endLane) {
1057  if (endPos < POSITION_EPS) {
1058  endPos = POSITION_EPS;
1059  }
1060  if (endPos > (endLane->getLaneShape().length() - POSITION_EPS)) {
1061  endPos = (endLane->getLaneShape().length() - POSITION_EPS);
1062  }
1063  }
1064 }
1065 
1066 
1067 void
1068 GNEGeometry::calculateLaneGeometricPath(GNEGeometry::SegmentGeometry& segmentGeometry, const std::vector<GNEPathElements::PathElement>& path, GNEGeometry::ExtremeGeometry& extremeGeometry) {
1069  // clear geometry
1070  segmentGeometry.clearSegmentGeometry();
1071  // first check that there is parent edges
1072  if (path.size() > 0) {
1073  // calculate depending if both from and to edges are the same
1074  if (path.size() == 1) {
1075  // filter start and end pos
1076  adjustStartPosGeometricPath(extremeGeometry.laneStartPosition, path.front().getLane(), extremeGeometry.laneEndPosition, path.front().getLane());
1077  // check if we have to define a new custom Segment, or we can use the commonLane shape
1078  if ((extremeGeometry.laneStartPosition != -1) || (extremeGeometry.laneEndPosition != -1) || (extremeGeometry.viewStartPos != Position::INVALID) || (extremeGeometry.viewEndPos != Position::INVALID)) {
1079  // declare a lane to be trimmed
1080  Geometry trimmedLane;
1081  // update geometry
1082  trimmedLane.updateGeometry(path.front().getLane()->getLaneShape(), extremeGeometry.laneStartPosition, extremeGeometry.laneEndPosition, extremeGeometry.viewStartPos, extremeGeometry.viewEndPos);
1083  // add sublane geometry
1084  segmentGeometry.insertCustomSegment(path.front().getLane(), trimmedLane, true);
1085  } else {
1086  // add entire lane geometry geometry
1087  segmentGeometry.insertLaneSegment(path.front().getLane(), true);
1088  }
1089  } else {
1090  // iterate over path
1091  for (int i = 0; i < (int)path.size(); i++) {
1092  // get lane (only for code readability)
1093  const GNELane* lane = path.at(i).getLane();
1094  // first check that lane shape isn't empty
1095  if (lane->getLaneShape().size() > 0) {
1096  // check if first or last lane must be splitted
1097  if ((path.at(i).getLane() == path.front().getLane()) && (extremeGeometry.laneStartPosition != -1)) {
1098  // filter start position
1099  adjustStartPosGeometricPath(extremeGeometry.laneStartPosition, path.at(i).getLane(), extremeGeometry.laneEndPosition, nullptr);
1100  // declare a lane to be trimmed
1101  Geometry frontTrimmedLane;
1102  // update geometry
1103  frontTrimmedLane.updateGeometry(path.at(i).getLane()->getLaneShape(), extremeGeometry.laneStartPosition, -1, extremeGeometry.viewStartPos, Position::INVALID);
1104  // add sublane geometry
1105  segmentGeometry.insertCustomSegment(lane, frontTrimmedLane, true);
1106  } else if ((lane == path.back().getLane()) && (extremeGeometry.laneEndPosition != -1)) {
1107  // filter end position
1108  adjustStartPosGeometricPath(extremeGeometry.laneStartPosition, nullptr, extremeGeometry.laneEndPosition, lane);
1109  // declare a lane to be trimmed
1110  Geometry backTrimmedLane;
1111  // update geometry
1112  backTrimmedLane.updateGeometry(path.at(i).getLane()->getLaneShape(), -1, extremeGeometry.laneEndPosition, Position::INVALID, extremeGeometry.viewEndPos);
1113  // add sublane geometry
1114  segmentGeometry.insertCustomSegment(lane, backTrimmedLane, true);
1115  } else {
1116  // add entire lane geometry
1117  segmentGeometry.insertLaneSegment(path.at(i).getLane(), true);
1118  }
1119  }
1120  // now continue with connection
1121  if ((i + 1) < (int)path.size()) {
1122  // obtain next lane
1123  const GNELane* nextLane = path.at(i + 1).getLane();
1124  // check that next lane exist
1125  if (lane->getLane2laneConnections().exist(nextLane)) {
1126  // add lane2laneConnection segment geometry
1127  segmentGeometry.insertLane2LaneSegment(lane, nextLane, true);
1128  }
1129  }
1130  }
1131  }
1132  }
1133 }
1134 
1135 
1136 void
1138  // calculate depending if both from and to edges are the same
1139  if ((segmentGeometry.size() == 1) && (segmentGeometry.front().getLane() == lane)) {
1140  // filter start and end pos
1141  adjustStartPosGeometricPath(extremeGeometry.laneStartPosition, segmentGeometry.front().getLane(), extremeGeometry.laneEndPosition, segmentGeometry.front().getLane());
1142  // check if we have to define a new custom Segment, or we can use the commonLane shape
1143  if ((extremeGeometry.laneStartPosition != -1) || (extremeGeometry.laneEndPosition != -1) || (extremeGeometry.viewStartPos != Position::INVALID) || (extremeGeometry.viewEndPos != Position::INVALID)) {
1144  // declare a lane to be trimmed
1145  Geometry trimmedLane;
1146  // update geometry
1147  trimmedLane.updateGeometry(segmentGeometry.front().getLane()->getLaneShape(), extremeGeometry.laneStartPosition, extremeGeometry.laneEndPosition, extremeGeometry.viewStartPos, extremeGeometry.viewEndPos);
1148  // add sublane geometry
1149  segmentGeometry.updateCustomSegment(0, trimmedLane);
1150  }
1151  } else {
1152  // declare a vector to save segments to update
1153  std::vector<GNEGeometry::SegmentGeometry::SegmentToUpdate> segmentsToUpdate;
1154  // iterate over all segments
1155  for (auto segment = segmentGeometry.begin(); segment != segmentGeometry.end(); segment++) {
1156  if (segment->getLane() == lane) {
1157  // obtain segment index
1158  const int index = (int)(segment - segmentGeometry.begin());
1159  // add SegmentToUpdate in vector
1160  segmentsToUpdate.push_back(GNEGeometry::SegmentGeometry::SegmentToUpdate(index, segment->getLane(), nullptr));
1161  // check if we have to add the next segment (it correspond to a lane2lane
1162  if (((segment + 1) != segmentGeometry.end()) && (segment + 1)->getJunction()) {
1163  segmentsToUpdate.push_back(GNEGeometry::SegmentGeometry::SegmentToUpdate(index, segment->getLane(), (segment + 1)->getLane()));
1164  }
1165  }
1166  }
1167  // iterate over segments to update
1168  for (const auto& segmentToUpdate : segmentsToUpdate) {
1169  // first check that lane shape isn't empty
1170  if (segmentToUpdate.getLane()->getLaneShape().size() > 0) {
1171  // check if first or last lane must be splitted
1172  if ((segmentToUpdate.getSegmentIndex() == 0) && (extremeGeometry.laneStartPosition != -1)) {
1173  // filter start position
1174  adjustStartPosGeometricPath(extremeGeometry.laneStartPosition, segmentToUpdate.getLane(), extremeGeometry.laneEndPosition, nullptr);
1175  // declare a lane to be trimmed
1176  Geometry frontTrimmedLane;
1177  // update geometry
1178  frontTrimmedLane.updateGeometry(segmentToUpdate.getLane()->getLaneShape(), extremeGeometry.laneStartPosition, -1, extremeGeometry.viewStartPos, Position::INVALID);
1179  // update segment
1180  segmentGeometry.updateCustomSegment(segmentToUpdate.getSegmentIndex(), frontTrimmedLane);
1181  } else if ((segmentToUpdate.getSegmentIndex() == (segmentGeometry.size() - 1)) && (extremeGeometry.laneEndPosition != -1)) {
1182  // filter end position
1183  adjustStartPosGeometricPath(extremeGeometry.laneStartPosition, nullptr, extremeGeometry.laneEndPosition, segmentToUpdate.getLane());
1184  // declare a lane to be trimmed
1185  Geometry backTrimmedLane;
1186  // update geometry
1187  backTrimmedLane.updateGeometry(segmentToUpdate.getLane()->getLaneShape(), -1, extremeGeometry.laneEndPosition, Position::INVALID, extremeGeometry.viewEndPos);
1188  // update segment
1189  segmentGeometry.updateCustomSegment(segmentToUpdate.getSegmentIndex(), backTrimmedLane);
1190  }
1191  }
1192  // check that next lane exist
1193  if (segmentToUpdate.getLane()->getLane2laneConnections().exist(segmentToUpdate.getNextLane())) {
1194  // update lane2laneConnection shape
1195  segmentGeometry.updateLane2LaneSegment(segmentToUpdate.getSegmentIndex(), segmentToUpdate.getLane(), segmentToUpdate.getNextLane());
1196  }
1197  }
1198  }
1199 }
1200 
1201 
1202 void
1203 GNEGeometry::drawGeometry(const GNEViewNet* viewNet, const Geometry& geometry, const double width) {
1204  // first check if we're in draw for selecting cliking mode
1206  // obtain mouse Position
1207  const Position mousePosition = viewNet->getPositionInformation();
1208  // obtain position over lane relative to mouse position
1209  const Position posOverLane = geometry.getShape().positionAtOffset2D(geometry.getShape().nearest_offset_to_point2D(mousePosition));
1210  // if mouse is over segment
1211  if (posOverLane.distanceSquaredTo2D(mousePosition) <= (width * width)) {
1212  // push matrix
1213  glPushMatrix();
1214  // translate to position over lane
1215  glTranslated(posOverLane.x(), posOverLane.y(), 0);
1216  // Draw circle
1218  // pop draw matrix
1219  glPopMatrix();
1220  }
1221  } else {
1222  GLHelper::drawBoxLines(geometry.getShape(), geometry.getShapeRotations(), geometry.getShapeLengths(), width);
1223  }
1224 }
1225 
1226 
1227 void
1229  const RGBColor& geometryPointColor, const RGBColor& textColor, const double radius, const double exaggeration) {
1230  // get mouse position
1231  const Position mousePosition = viewNet->getPositionInformation();
1232  // get exaggeratedRadio
1233  const double exaggeratedRadio = (radius * exaggeration);
1234  // get radius squared
1235  const double exaggeratedRadioSquared = (exaggeratedRadio * exaggeratedRadio);
1236  // iterate over shape
1237  for (const auto& vertex : shape) {
1238  // if drawForPositionSelection is enabled, check distance between mouse and vertex
1239  if (!s.drawForPositionSelection || (mousePosition.distanceSquaredTo2D(vertex) <= exaggeratedRadioSquared)) {
1240  // push geometry point matrix
1241  glPushMatrix();
1242  // move to vertex
1243  glTranslated(vertex.x(), vertex.y(), 0.2);
1244  // set color
1245  GLHelper::setColor(geometryPointColor);
1246  // draw circle
1247  GLHelper::drawFilledCircle(exaggeratedRadio, s.getCircleResolution());
1248  // pop geometry point matrix
1249  glPopMatrix();
1250  // draw elevation or special symbols (Start, End and Block)
1252  // get draw detail
1253  const bool drawDetail = s.drawDetail(s.detailSettings.geometryPointsText, exaggeration);
1254  // draw text
1255  if (viewNet->getNetworkViewOptions().editingElevation()) {
1256  // Push Z matrix
1257  glPushMatrix();
1258  // draw Z (elevation)
1259  GLHelper::drawText(toString(vertex.z()), vertex, 0.3, 0.7, textColor);
1260  // pop Z matrix
1261  glPopMatrix();
1262  } else if ((vertex == shape.front()) && drawDetail) {
1263  // push "S" matrix
1264  glPushMatrix();
1265  // draw a "s" over first point
1266  GLHelper::drawText("S", vertex, 0.3, 2 * exaggeratedRadio, textColor);
1267  // pop "S" matrix
1268  glPopMatrix();
1269  } else if ((vertex == shape.back()) && (shape.isClosed() == false) && drawDetail) {
1270  // push "E" matrix
1271  glPushMatrix();
1272  // draw a "e" over last point if polygon isn't closed
1273  GLHelper::drawText("E", vertex, 0.3, 2 * exaggeratedRadio, textColor);
1274  // pop "E" matrix
1275  glPopMatrix();
1276  }
1277  }
1278  }
1279  }
1280 }
1281 
1282 
1283 void
1285  const RGBColor& hintColor, const double radius, const double exaggeration) {
1286  // first NetworkEditMode
1288  // get mouse position
1289  const Position mousePosition = viewNet->getPositionInformation();
1290  // get exaggeratedRadio
1291  const double exaggeratedRadio = (radius * exaggeration);
1292  // obtain distance to shape
1293  const double distanceToShape = shape.distance2D(mousePosition);
1294  // obtain squared radius
1295  const double squaredRadius = (radius * radius * exaggeration);
1296  // declare index
1297  int index = -1;
1298  // iterate over shape
1299  for (int i = 0; i < (int)shape.size(); i++) {
1300  // check distance
1301  if (shape[i].distanceSquaredTo2D(mousePosition) <= squaredRadius) {
1302  index = i;
1303  }
1304  }
1305  // continue depending of distance to shape
1306  if ((distanceToShape < exaggeratedRadio) && (index == -1)) {
1307  // obtain position over lane
1308  const Position positionOverLane = shape.positionAtOffset2D(shape.nearest_offset_to_point2D(mousePosition));
1309  // calculate hintPos
1310  const Position hintPos = shape.size() > 1 ? positionOverLane : shape[0];
1311  // push hintPos matrix
1312  glPushMatrix();
1313  // translate to hintPos
1314  glTranslated(hintPos.x(), hintPos.y(), 0.2);
1315  // set color
1316  GLHelper::setColor(hintColor);
1317  // draw filled circle
1318  GLHelper:: drawFilledCircle(exaggeratedRadio, s.getCircleResolution());
1319  // pop hintPos matrix
1320  glPopMatrix();
1321  }
1322  }
1323 }
1324 
1325 
1326 void
1327 GNEGeometry::drawLaneGeometry(const GNEViewNet* viewNet, const PositionVector& shape, const std::vector<double>& rotations,
1328  const std::vector<double>& lengths, const std::vector<RGBColor>& colors, double width) {
1329  // first check if we're in draw for selecting cliking mode
1331  // obtain mouse Position
1332  const Position mousePosition = viewNet->getPositionInformation();
1333  // obtain position over lane relative to mouse position
1334  const Position posOverLane = shape.positionAtOffset2D(shape.nearest_offset_to_point2D(mousePosition));
1335  // if mouse is over segment
1336  if (posOverLane.distanceSquaredTo2D(mousePosition) <= (width * width)) {
1337  // push matrix
1338  glPushMatrix();
1339  // translate to position over lane
1340  glTranslated(posOverLane.x(), posOverLane.y(), 0);
1341  // Draw circle
1343  // pop draw matrix
1344  glPopMatrix();
1345  }
1346  } else if (colors.size() > 0) {
1347  // draw box lines with own colors
1348  GLHelper::drawBoxLines(shape, rotations, lengths, colors, width);
1349  } else {
1350  // draw box lines with current color
1351  GLHelper::drawBoxLines(shape, rotations, lengths, width);
1352  }
1353 }
1354 
1355 
1356 void
1357 GNEGeometry::drawSegmentGeometry(const GNEViewNet* viewNet, const SegmentGeometry::Segment& segment, const double width) {
1358  // first check if we're in draw for selecting mode
1360  // obtain mouse Position
1361  const Position mousePosition = viewNet->getPositionInformation();
1362  // obtain position over lane relative to mouse position
1363  const Position posOverLane = segment.getShape().positionAtOffset2D(segment.getShape().nearest_offset_to_point2D(mousePosition));
1364  // if mouse is over segment
1365  if (posOverLane.distanceSquaredTo2D(mousePosition) <= (width * width)) {
1366  // push matrix
1367  glPushMatrix();
1368  // translate to position over lane
1369  glTranslated(posOverLane.x(), posOverLane.y(), 0);
1370  // Draw circle
1372  // pop draw matrix
1373  glPopMatrix();
1374  }
1375  } else {
1376  // draw a boxline as usual
1377  GLHelper::drawBoxLines(segment.getShape(), segment.getShapeRotations(), segment.getShapeLengths(), width);
1378  }
1379 }
1380 
1381 
1382 void
1383 GNEGeometry::drawDottedContourLane(const DottedContourType type, const GUIVisualizationSettings& s, const DottedGeometry& dottedGeometry, const double width, const bool drawFirstExtrem, const bool drawLastExtrem) {
1384  // declare DottedGeometryColor
1385  DottedGeometryColor dottedGeometryColor(s);
1386  // make a copy of dotted geometry
1387  DottedGeometry topDottedGeometry = dottedGeometry;
1388  DottedGeometry botDottedGeometry = dottedGeometry;
1389  // move geometries
1390  topDottedGeometry.moveShapeToSide(width);
1391  botDottedGeometry.moveShapeToSide(width * -1);
1392  // invert offset of top dotted geometry
1393  topDottedGeometry.invertOffset();
1394  // calculate extremes
1395  DottedGeometry extremes(s, topDottedGeometry, drawFirstExtrem, botDottedGeometry, drawLastExtrem);
1396  // Push draw matrix
1397  glPushMatrix();
1398  // draw inspect or front dotted contour
1399  if (type == DottedContourType::INSPECT) {
1400  // translate to front
1401  glTranslated(0, 0, GLO_DOTTEDCONTOUR_INSPECTED);
1402  // draw top dotted geometry
1403  topDottedGeometry.drawInspectedDottedGeometry(dottedGeometryColor);
1404  // reset color
1405  dottedGeometryColor.reset();
1406  // draw top dotted geometry
1407  botDottedGeometry.drawInspectedDottedGeometry(dottedGeometryColor);
1408  // change color
1409  dottedGeometryColor.changeColor();
1410  // draw extrem dotted geometry
1411  extremes.drawInspectedDottedGeometry(dottedGeometryColor);
1412  } else if (type == DottedContourType::FRONT) {
1413  // translate to front
1414  glTranslated(0, 0, GLO_DOTTEDCONTOUR_FRONT);
1415  // draw top dotted geometry
1416  topDottedGeometry.drawFrontDottedGeometry(dottedGeometryColor);
1417  // reset color
1418  dottedGeometryColor.reset();
1419  // draw top dotted geometry
1420  botDottedGeometry.drawFrontDottedGeometry(dottedGeometryColor);
1421  // change color
1422  dottedGeometryColor.changeColor();
1423  // draw extrem dotted geometry
1424  extremes.drawFrontDottedGeometry(dottedGeometryColor);
1425  }
1426  // pop matrix
1427  glPopMatrix();
1428 }
1429 
1430 
1431 void
1432 GNEGeometry::drawDottedContourEdge(const DottedContourType type, const GUIVisualizationSettings& s, const GNEEdge* edge, const bool drawFrontExtreme, const bool drawBackExtreme) {
1433  if (edge->getLanes().size() == 1) {
1434  GNELane::LaneDrawingConstants laneDrawingConstants(s, edge->getLanes().front());
1435  GNEGeometry::drawDottedContourLane(type, s, edge->getLanes().front()->getDottedLaneGeometry(), laneDrawingConstants.halfWidth, drawFrontExtreme, drawBackExtreme);
1436  } else {
1437  // set left hand flag
1438  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
1439  // obtain lanes
1440  const GNELane* topLane = lefthand ? edge->getLanes().back() : edge->getLanes().front();
1441  const GNELane* botLane = lefthand ? edge->getLanes().front() : edge->getLanes().back();
1442  // obtain a copy of both geometries
1443  GNEGeometry::DottedGeometry dottedGeometryTop = topLane->getDottedLaneGeometry();
1444  GNEGeometry::DottedGeometry dottedGeometryBot = botLane->getDottedLaneGeometry();
1445  // obtain both LaneDrawingConstants
1446  GNELane::LaneDrawingConstants laneDrawingConstantsFront(s, topLane);
1447  GNELane::LaneDrawingConstants laneDrawingConstantsBack(s, botLane);
1448  // move shapes to side
1449  dottedGeometryTop.moveShapeToSide(laneDrawingConstantsFront.halfWidth);
1450  dottedGeometryBot.moveShapeToSide(laneDrawingConstantsBack.halfWidth * -1);
1451  // invert offset of top dotted geometry
1452  dottedGeometryTop.invertOffset();
1453  // declare DottedGeometryColor
1454  DottedGeometryColor dottedGeometryColor(s);
1455  // calculate extremes
1456  DottedGeometry extremes(s, dottedGeometryTop, drawFrontExtreme, dottedGeometryBot, drawBackExtreme);
1457  // Push draw matrix
1458  glPushMatrix();
1459  // draw inspect or front dotted contour
1460  if (type == DottedContourType::INSPECT) {
1461  // translate to front
1462  glTranslated(0, 0, GLO_DOTTEDCONTOUR_INSPECTED);
1463  // draw top dotted geometry
1464  dottedGeometryTop.drawInspectedDottedGeometry(dottedGeometryColor);
1465  // reset color
1466  dottedGeometryColor.reset();
1467  // draw top dotted geometry
1468  dottedGeometryBot.drawInspectedDottedGeometry(dottedGeometryColor);
1469  // change color
1470  dottedGeometryColor.changeColor();
1471  // draw extrem dotted geometry
1472  extremes.drawInspectedDottedGeometry(dottedGeometryColor);
1473  } else if (type == DottedContourType::FRONT) {
1474  // translate to front
1475  glTranslated(0, 0, GLO_DOTTEDCONTOUR_FRONT);
1476  // draw top dotted geometry
1477  dottedGeometryTop.drawFrontDottedGeometry(dottedGeometryColor);
1478  // reset color
1479  dottedGeometryColor.reset();
1480  // draw top dotted geometry
1481  dottedGeometryBot.drawFrontDottedGeometry(dottedGeometryColor);
1482  // change color
1483  dottedGeometryColor.changeColor();
1484  // draw extrem dotted geometry
1485  extremes.drawFrontDottedGeometry(dottedGeometryColor);
1486  }
1487  // pop matrix
1488  glPopMatrix();
1489  }
1490 }
1491 
1492 
1493 void
1494 GNEGeometry::drawDottedContourClosedShape(const DottedContourType type, const GUIVisualizationSettings& s, const PositionVector& shape, const double exaggeration) {
1495  if (exaggeration > 0) {
1496  // declare DottedGeometryColor
1497  DottedGeometryColor dottedGeometryColor(s);
1498  // scale shape using exaggeration and default dotted geometry width
1499  PositionVector scaledShape = shape;
1500  // scale exaggeration
1501  scaledShape.scaleRelative(exaggeration);
1502  // calculate dotted geometry
1503  GNEGeometry::DottedGeometry dottedGeometry(s, scaledShape, true);
1504  // Push draw matrix
1505  glPushMatrix();
1506  // draw inspect or front dotted contour
1507  if (type == DottedContourType::INSPECT) {
1508  // translate to front
1509  glTranslated(0, 0, GLO_DOTTEDCONTOUR_INSPECTED);
1510  // draw dotted geometry
1511  dottedGeometry.drawInspectedDottedGeometry(dottedGeometryColor);
1512  } else {
1513  // translate to front
1514  glTranslated(0, 0, GLO_DOTTEDCONTOUR_FRONT);
1515  // draw dotted geometry
1516  dottedGeometry.drawFrontDottedGeometry(dottedGeometryColor);
1517  }
1518  // pop matrix
1519  glPopMatrix();
1520  }
1521 }
1522 
1523 
1524 void
1525 GNEGeometry::drawDottedContourShape(const DottedContourType type, const GUIVisualizationSettings& s, const PositionVector& shape, const double width, const double exaggeration) {
1526  // calculate dotted geometry
1527  GNEGeometry::DottedGeometry dottedGeometry(s, shape, false);
1528  // use drawDottedContourLane to draw it
1529  drawDottedContourLane(type, s, dottedGeometry, width * exaggeration, true, true);
1530 }
1531 
1532 
1533 void
1534 GNEGeometry::drawDottedContourCircle(const DottedContourType type, const GUIVisualizationSettings& s, const Position& pos, const double radius, const double exaggeration) {
1535  // continue depending of exaggeratedRadio
1536  if ((radius * exaggeration) < 2) {
1537  drawDottedContourClosedShape(type, s, getVertexCircleAroundPosition(pos, radius, 8), exaggeration);
1538  } else {
1539  drawDottedContourClosedShape(type, s, getVertexCircleAroundPosition(pos, radius, 16), exaggeration);
1540  }
1541 }
1542 
1543 
1544 void
1546  const double width, const double height, const double offsetX, const double offsetY, const double rot, const double exaggeration) {
1547  // create shape
1548  PositionVector shape;
1549  // make rectangle
1550  shape.push_back(Position(0 + width, 0 + height));
1551  shape.push_back(Position(0 + width, 0 - height));
1552  shape.push_back(Position(0 - width, 0 - height));
1553  shape.push_back(Position(0 - width, 0 + height));
1554  // move shape
1555  shape.add(offsetX, offsetY, 0);
1556  // rotate shape
1557  shape.rotate2D(DEG2RAD((rot * -1) + 90));
1558  // move to position
1559  shape.add(pos);
1560  // draw using drawDottedContourClosedShape
1561  drawDottedContourClosedShape(type, s, shape, exaggeration);
1562 }
1563 
1564 
1566 GNEGeometry::getVertexCircleAroundPosition(const Position& pos, const double width, const int steps) {
1567  // first check if we have to fill myCircleCoords (only once)
1568  if (myCircleCoords.size() == 0) {
1569  for (int i = 0; i <= (int)(360 * CIRCLE_RESOLUTION); ++i) {
1570  const double x = (double) sin(DEG2RAD(i / CIRCLE_RESOLUTION));
1571  const double y = (double) cos(DEG2RAD(i / CIRCLE_RESOLUTION));
1572  myCircleCoords.push_back(Position(x, y));
1573  }
1574  }
1575  PositionVector vertexCircle;
1576  const double inc = 360 / (double)steps;
1577  // obtain all vertices
1578  for (int i = 0; i <= steps; ++i) {
1579  const Position& vertex = myCircleCoords[GNEGeometry::angleLookup(i * inc)];
1580  vertexCircle.push_back(Position(vertex.x() * width, vertex.y() * width));
1581  }
1582  // move result using position
1583  vertexCircle.add(pos);
1584  return vertexCircle;
1585 }
1586 
1587 
1588 void
1589 GNEGeometry::rotateOverLane(const double rot) {
1590  // rotate using rotation calculated in PositionVector
1591  glRotated((rot * -1) + 90, 0, 0, 1);
1592 }
1593 
1594 
1595 int
1596 GNEGeometry::angleLookup(const double angleDeg) {
1597  const int numCoords = (int)myCircleCoords.size() - 1;
1598  int index = ((int)(floor(angleDeg * CIRCLE_RESOLUTION + 0.5))) % numCoords;
1599  if (index < 0) {
1600  index += numCoords;
1601  }
1602  assert(index >= 0);
1603  return (int)index;
1604 }
1605 
1606 
1607 /****************************************************************************/
#define CIRCLE_RESOLUTION
Definition: GNEGeometry.cpp:30
@ NETWORK_MOVE
mode for moving network elements
@ GLO_DOTTEDCONTOUR_INSPECTED
dotted contour inspected element (used in NETEDIT)
@ GLO_DOTTEDCONTOUR_FRONT
dotted contour front element (used in NETEDIT)
#define DEG2RAD(x)
Definition: GeomHelper.h:35
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:39
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:77
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:446
static void drawFilledCircle(double width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:347
static void drawBoxLines(const PositionVector &geom, const std::vector< double > &rots, const std::vector< double > &lengths, double width, int cornerDetail=0, double offset=0)
Draws thick lines.
Definition: GLHelper.cpp:181
static void drawBoxLine(const Position &beg, double rot, double visLength, double width, double offset=0)
Draws a thick line.
Definition: GLHelper.cpp:135
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, const int align=0, double width=-1)
Definition: GLHelper.cpp:498
An Element which don't belongs to GNENet but has influency in the simulation.
Definition: GNEAdditional.h:47
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:49
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition: GNEEdge.cpp:723
class for pack all variables related with DottedGeometry color
Definition: GNEGeometry.h:157
DottedGeometryColor(const GUIVisualizationSettings &settings)
constructor
void reset()
rest Dotted Geometry Color
const RGBColor & getFrontColor()
get front color (and change flag)
const RGBColor & getInspectedColor()
get inspected color (and change flag)
class for pack all variables related with DottedGeometry
Definition: GNEGeometry.h:187
void moveShapeToSide(const double value)
move shape to side
double getWidth() const
get width
double myWidth
geometry width
Definition: GNEGeometry.h:251
void updateDottedGeometry(const GUIVisualizationSettings &s, const GNELane *lane)
update DottedGeometry (using lane shape)
void drawFrontDottedGeometry(DottedGeometryColor &dottedGeometryColor) const
draw front inspected dottedShape
void drawInspectedDottedGeometry(DottedGeometryColor &dottedGeometryColor) const
draw inspected dottedShape
void calculateShapeRotationsAndLengths()
calculate shape rotations and lengths
std::vector< DottedGeometry::Segment > myDottedGeometrySegments
dotted element shape (note: It's centered in 0,0 due scaling)
Definition: GNEGeometry.h:254
void setWidth(const double width)
change default width
void invertOffset()
invert offset of all segments
class for NETEDIT geometries over lanes
Definition: GNEGeometry.h:76
const std::vector< double > & getShapeRotations() const
The rotations of the single shape parts.
Geometry()
constructor
Definition: GNEGeometry.cpp:56
void scaleGeometry(const double scale)
scale geometry
void calculateShapeRotationsAndLengths()
calculate shape rotations and lengths
const PositionVector & getShape() const
The shape of the additional element.
void clearGeometry()
clear geometry
void updateGeometry(const PositionVector &shape, double startPos=-1, double endPos=-1, const Position &extraFirstPosition=Position::INVALID, const Position &extraLastPosition=Position::INVALID)
update geometry shape
Definition: GNEGeometry.cpp:81
const std::vector< double > & getShapeLengths() const
The lengths of the single shape parts.
const Position & getPosition() const
get position
void drawConnection(const GUIVisualizationSettings &s, const GNEAttributeCarrier *AC, const double exaggeration) const
draw connections between Parent and childrens
void update()
update Connection's geometry
GNEHierarchicalElement * myHierarchicalElement
pointer to hierarchical element parent
Definition: GNEGeometry.h:500
HierarchicalConnections(GNEHierarchicalElement *hierarchicalElement)
constructor
void drawDottedConnection(const DottedContourType type, const GUIVisualizationSettings &s, const double exaggeration) const
draw dotted connections between Parent and childrens
bool exist(const GNELane *toLane) const
check if exist a lane2lane geometry for the given tolane
const GNEGeometry::Geometry & getLane2laneGeometry(const GNELane *toLane) const
get lane2lane geometry
const GNEGeometry::DottedGeometry & getLane2laneDottedGeometry(const GNELane *toLane) const
get lane2lane dotted geometry
struct used for represent segments of element geometry
Definition: GNEGeometry.h:264
Segment(const GNELane *lane, const bool valid)
parameter constructor for lanes (geometry will be taked from lane)
const std::vector< double > & getShapeRotations() const
get lane/lane2lane shape rotations
const PositionVector & getShape() const
get lane/lane2lane shape
bool isLaneSegment() const
return true if this is a lane segment (i.e. myNextLane is nullptr)
const GNELane * getLane() const
lane (only for lane segments)
const std::vector< double > & getShapeLengths() const
get lane/lane2lane shape lengths
const GNEJunction * getJunction() const
junction
void update(const Geometry &geometry)
update segment using geometry
struct used for represent segments that must be updated
Definition: GNEGeometry.h:325
int getSegmentIndex() const
get segment index
SegmentToUpdate(const int segmentIndex, const GNELane *lane, const GNELane *nextLane)
constructor
const GNELane * getNextLane() const
get lane segment (used for updating lane2lane segments)
const std::vector< GNEJunction * > & getParentJunctions() const
get parent junctions
FOX-declaration.
Definition: GNELane.h:51
const double halfWidth
Draw as a normal lane, and reduce width to make sure that a selected edge can still be seen.
Definition: GNELane.h:67
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:45
const PositionVector & getLaneShape() const
Definition: GNELane.cpp:117
const GNEGeometry::DottedGeometry & getDottedLaneGeometry() const
get dotted lane geometry
Definition: GNELane.cpp:135
const GNEGeometry::Lane2laneConnection & getLane2laneConnections() const
get Lane2laneConnection struct
Definition: GNELane.cpp:774
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
Definition: GNEViewNet.cpp:467
const GNEViewNetHelper::NetworkViewOptions & getNetworkViewOptions() const
get network view options
Definition: GNEViewNet.cpp:479
GUIVisualizationSettings & getVisualisationSettings() const
get visualization settings
Position getPositionInformation() const
Returns the cursor's x/y position within the network.
Stores the information about how to visualize structures.
bool drawForRectangleSelection
whether drawing is performed for the purpose of selecting objects using a rectangle
GUIVisualizationDetailSettings detailSettings
detail settings
bool drawForPositionSelection
whether drawing is performed for the purpose of selecting objects with a single click
GUIVisualizationColorSettings colorSettings
color settings
GUIVisualizationDottedContourSettings dottedContourSettings
dotted contour settings
bool drawDetail(const double detail, const double exaggeration) const
check if details can be drawn for the given GUIVisualizationDetailSettings and current scale and exxa...
int getCircleResolution() const
function to calculate circle resolution for all circles drawn in drawGL(...) functions
The representation of a single edge during network building.
Definition: NBEdge.h:91
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:516
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:490
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3336
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:901
PositionVector computeSmoothShape(const PositionVector &begShape, const PositionVector &endShape, int numPoints, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, NBNode *recordError=0, int shapeFlag=0) const
Compute a smooth curve between the given geometries.
Definition: NBNode.cpp:513
const PositionVector & getShape() const
retrieve the junction shape
Definition: NBNode.cpp:2285
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:36
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
Definition: Position.h:246
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:282
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:241
double x() const
Returns the x-position.
Definition: Position.h:54
double y() const
Returns the y-position.
Definition: Position.h:59
A list of positions.
double length() const
Returns the length.
void rotate2D(double angle)
double rotationDegreeAtOffset(double pos) const
Returns the rotation at the given length.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
void add(double xoff, double yoff, double zoff)
void closePolygon()
ensures that the last position equals the first
double distance2D(const Position &p, bool perpendicular=false) const
closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector)
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
std::pair< PositionVector, PositionVector > splitAt(double where, bool use2D=false) const
Returns the two lists made when this list vector is splitted at the given point.
void scaleRelative(double factor)
enlarges/shrinks the polygon by a factor based at the centroid
double area() const
Returns the area (0 for non-closed)
bool isClosed() const
check if PositionVector is closed
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
RGBColor changedBrightness(int change, int toChange=3) const
Returns a new color with altered brightness.
Definition: RGBColor.cpp:145
#define M_PI
Definition: odrSpiral.cpp:40
struct for variables used in Geometry extremes
Definition: GNEGeometry.h:58
double laneEndPosition
arrival position over lane
Definition: GNEGeometry.h:66
Position viewEndPos
end position over view
Definition: GNEGeometry.h:72
double laneStartPosition
depart position over lane
Definition: GNEGeometry.h:63
Position viewStartPos
start position over view
Definition: GNEGeometry.h:69
struct for pack all variables related with geometry of elemements divided in segments
Definition: GNEGeometry.h:261
void insertCustomSegment(const GNELane *lane, const Geometry &geometry, const bool valid)
insert custom segment
int size() const
number of segments
void updateCustomSegment(const int segmentIndex, const Geometry &geometry)
update custom segment
const Segment & back() const
back segment
std::vector< Segment >::const_iterator end() const
end iterator
const Position & getFirstPosition() const
get first position (or Invalid position if segments are empty)
const Position & getLastPosition() const
get first position (or Invalid position if segments are empty)
void updateLane2LaneSegment(const int segmentIndex, const GNELane *lane, const GNELane *nextLane)
update lane2Lane segment (used to avoid unnecessary calculation in calculatePartialShapeRotationsAndL...
void insertLaneSegment(const GNELane *lane, const bool valid)
insert entire lane segment (used to avoid unnecessary calculation in calculatePartialShapeRotationsAn...
std::vector< Segment > myShapeSegments
vector of segments that constitutes the shape
Definition: GNEGeometry.h:405
std::vector< Segment >::const_iterator begin() const
begin iterator
double getFirstRotation() const
get first rotation (or Invalid position if segments are empty)
const Segment & front() const
front segment
void clearSegmentGeometry()
clear element geometry
void insertLane2LaneSegment(const GNELane *currentLane, const GNELane *nextLane, const bool valid)
insert entire lane2lane segment (used to avoid unnecessary calculation in calculatePartialShapeRotati...
Boundary getBoxBoundary() const
Returns a boundary enclosing all segments.
static void drawDottedContourClosedShape(const DottedContourType type, const GUIVisualizationSettings &s, const PositionVector &shape, const double exaggeration)
draw dotted contour for the given closed shape (used by Juctions, shapes and TAZs)
static void drawGeometryPoints(const GUIVisualizationSettings &s, const GNEViewNet *viewNet, const PositionVector &shape, const RGBColor &geometryPointColor, const RGBColor &textColor, const double radius, const double exaggeration)
draw geometry points
static void drawDottedContourLane(const DottedContourType type, const GUIVisualizationSettings &s, const DottedGeometry &dottedGeometry, const double width, const bool drawFirstExtrem, const bool drawLastExtrem)
draw dotted contour for the given dottedGeometry (used by lanes, routes, etc.)
static double calculateRotation(const Position &first, const Position &second)
return angle between two points (used in geometric calculations)
static void adjustStartPosGeometricPath(double &startPos, const GNELane *startLane, double &endPos, const GNELane *endLane)
adjust start and end positions in geometric path
static void drawDottedContourShape(const DottedContourType type, const GUIVisualizationSettings &s, const PositionVector &shape, const double width, const double exaggeration)
draw dotted contour for the given shape (used by additionals)
static PositionVector getVertexCircleAroundPosition(const Position &pos, const double width, const int steps=8)
get a circle around the given position
static void calculateLaneGeometricPath(GNEGeometry::SegmentGeometry &segmentGeometry, const std::vector< GNEPathElements::PathElement > &path, GNEGeometry::ExtremeGeometry &extremeGeometry)
calculate route between lanes
static void rotateOverLane(const double rot)
rotate over lane (used by Lock icons, detector logos, etc.)
static PositionVector myCircleCoords
Storage for precomputed sin/cos-values describing a circle.
Definition: GNEGeometry.h:574
static void updateGeometricPath(GNEGeometry::SegmentGeometry &segmentGeometry, const GNELane *lane, GNEGeometry::ExtremeGeometry &extremeGeometry)
calculate route between edges
static void drawDottedContourEdge(const DottedContourType type, const GUIVisualizationSettings &s, const GNEEdge *edge, const bool drawFrontExtreme, const bool drawBackExtreme)
draw dotted contour for the given dottedGeometries (used by edges)
static void drawSegmentGeometry(const GNEViewNet *viewNet, const SegmentGeometry::Segment &segment, const double width)
draw geometry segment
static void drawGeometry(const GNEViewNet *viewNet, const Geometry &geometry, const double width)
draw geometry
static void drawMovingHint(const GUIVisualizationSettings &s, const GNEViewNet *viewNet, const PositionVector &shape, const RGBColor &hintColor, const double radius, const double exaggeration)
draw moving hint
static void drawDottedContourCircle(const DottedContourType type, const GUIVisualizationSettings &s, const Position &pos, const double radius, const double exaggeration)
draw dotted contour for the given Position and radius (used by Juctions and POIs)
static void drawDottedSquaredShape(const DottedContourType type, const GUIVisualizationSettings &s, const Position &pos, const double width, const double height, const double offsetX, const double offsetY, const double rot, const double exaggeration)
draw dotted squared contour (used by additionals and demand elements)
static int angleLookup(const double angleDeg)
normalize angle for lookup in myCircleCoords
static double calculateLength(const Position &first, const Position &second)
return length between two points (used in geometric calculations)
static void drawLaneGeometry(const GNEViewNet *viewNet, const PositionVector &shape, const std::vector< double > &rotations, const std::vector< double > &lengths, const std::vector< RGBColor > &colors, double width)
draw lane geometry (use their own function due colors)
NetworkEditMode networkEditMode
the current Network edit mode
bool editingElevation() const
check if we're editing elevation
RGBColor selectedAdditionalColor
additional selection color (busStops, Detectors...)
static const RGBColor childConnections
color for child connections between parents and child elements
static const double geometryPointsText
details for Geometry Points Texts
static const double segmentWidth
width of dotted contour segments
static const double segmentLength
length of dotted contour segments