MATSIM
VisLaneModelBuilder.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * OTFLaneModelBuilder
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2012 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 package org.matsim.lanes;
21 
22 import java.awt.geom.Point2D;
23 import java.awt.geom.Point2D.Double;
24 import java.util.List;
25 import java.util.Map;
26 
27 import org.matsim.api.core.v01.Coord;
28 import org.matsim.api.core.v01.Id;
35 
39 public final class VisLaneModelBuilder {
40 
41 // private static final Logger log = LogManager.getLogger(VisLaneModelBuilder.class);
42 
43  public void recalculatePositions(VisLinkWLanes linkData, SnapshotLinkWidthCalculator linkWidthCalculator) {
44 // log.error("recalculatePositions...");
45  double linkWidth = linkWidthCalculator.calculateLinkWidth(linkData.getNumberOfLanes()) ;
46  linkData.setLinkWidth(linkWidth);
47  Point2D.Double linkStartCenter = this.calculatePointOnLink(linkData, 0.0, 0.5);
48  linkData.setLinkStartCenterPoint(linkStartCenter);
49  if (linkData.getLaneData() == null || linkData.getLaneData().isEmpty()){
50  //Calculate end point center
51  double x = linkData.getLinkEnd().x + (0.5 * linkWidth * linkData.getLinkOrthogonalVector().x);
52  double y = linkData.getLinkEnd().y + (0.5 * linkWidth * linkData.getLinkOrthogonalVector().y);
53  linkData.setLinkEndCenterPoint(new Point2D.Double(x, y));
54 // log.error("link " + linkData.getLinkId() + " without lanes starts at " + linkData.getLinkStartCenterPoint() + " and ends at " + x + " " + y + " but " + linkData.getLinkEnd());
55  }
56  else {
57  double numberOfLinkParts = (2 * linkData.getMaximalAlignment()) + 2;
58 // log.error("link with lanes " + linkData.getLinkId() + " starts at " + linkData.getLinkStart() + " and ends at " + linkData.getLinkEnd());
59  for (VisLane lane : linkData.getLaneData().values()){
60  double horizontalFraction = 0.5 - (lane.getAlignment() / numberOfLinkParts);
61  Point2D.Double laneStart = calculatePointOnLink(linkData, lane.getStartPosition(), horizontalFraction);
62  Point2D.Double laneEnd = calculatePointOnLink(linkData, lane.getEndPosition(), horizontalFraction);
63  lane.setStartEndPoint(laneStart, laneEnd);
64 // log.error("lane " + lane.getId() + " starts at " + laneStart + " ends at " + laneEnd);
65  if (lane.getNumberOfLanes() >= 2.0){
66  double noLanesFloor = Math.floor(lane.getNumberOfLanes());
67  double laneOffset = - noLanesFloor / 2 * linkWidthCalculator.getLaneWidth();
68  if (noLanesFloor % 2 == 0){
69  laneOffset = laneOffset + (linkWidthCalculator.getLaneWidth()/2);
70  }
71  for (int i = 1; i <= noLanesFloor; i++){
72  Point2D.Double drivingLaneStart = this.calcPoint(laneStart, linkData.getLinkOrthogonalVector(), laneOffset);
73  Point2D.Double drivingLaneEnd = this.calcPoint(laneEnd, linkData.getLinkOrthogonalVector(), laneOffset);
74  lane.addDrivingLane(i, drivingLaneStart, drivingLaneEnd);
75  laneOffset = laneOffset + linkWidthCalculator.getLaneWidth();
76  }
77  }
78  }
79  }
80  }
81 
82  private Point2D.Double calculatePointOnLink(final VisLinkWLanes laneLinkData, final double position, final double horizontalFraction) {
83  Point2D.Double lenghtPoint = this.calcPoint(laneLinkData.getLinkStart(), laneLinkData.getNormalizedLinkVector(), position);
84  return this.calcPoint(lenghtPoint, laneLinkData.getLinkOrthogonalVector(), horizontalFraction * laneLinkData.getLinkWidth());
85  }
86 
87  public Point2D.Double calcPoint(Point2D.Double start, Point2D.Double vector, double distance){
88  double x = start.getX() + (distance * vector.x);
89  double y = start.getY() + (distance * vector.y);
90  return new Point2D.Double(x, y);
91  }
92 
93  private VisLane createVisLane(ModelLane qlane, double linkLength, double linkScale, double linkLengthCorrectionFactor) {
94  String id = qlane.getLaneData().getId().toString();
95  double startPosition = (linkLength - qlane.getLaneData().getStartsAtMeterFromLinkEnd()) * linkScale * linkLengthCorrectionFactor;
96  double endPosition = startPosition + (qlane.getLength() * linkScale * linkLengthCorrectionFactor);
97 // log.error("lane " + qlane.getId() + " starts at: " + startPosition + " and ends at : " +endPosition);
98  int alignment = qlane.getLaneData().getAlignment();
99  VisLane lane = new VisLane(id);
100  lane.setStartPosition(startPosition);
101  lane.setEndPosition(endPosition);
102  lane.setAlignment(alignment);
104  return lane;
105  }
106 
107 
108 
109  public void connect(Map<String, VisLinkWLanes> otfNetwork){
110  for (VisLinkWLanes otfLink : otfNetwork.values()){
111  if (otfLink.getLaneData() == null || otfLink.getLaneData().isEmpty()){
112  if (otfLink.getToLinkIds() != null){
113  for (String toLinkId : otfLink.getToLinkIds()){
114  VisLinkWLanes toLink = otfNetwork.get(toLinkId);
115  otfLink.addToLink(toLink);
116  }
117  }
118  }
119  else {
120  for (VisLane otfLane : otfLink.getLaneData().values()){
121  if (otfLane.getToLinkIds() != null) {
122  for (String toLinkId : otfLane.getToLinkIds()){
123  VisLinkWLanes toLink = otfNetwork.get(toLinkId);
124  otfLane.addToLink(toLink);
125  }
126  }
127  }
128  }
129  }
130  }
131 
132  public VisLinkWLanes createVisLinkLanes(CoordinateTransformation transform, VisLink link, double nodeOffsetMeter, List<ModelLane> lanes) {
133 // log.error("");
134 // log.error("link " + link.getLink().getId() + " ... ");
135 // log.debug(" fromNode: " + link.getLink().getFromNode().getId() + " coord: " + link.getLink().getFromNode().getCoord());
136 // log.debug(" toNode: " + link.getLink().getToNode().getId() + " coord: " + link.getLink().getToNode().getCoord());
137  Coord linkStartCoord = transform.transform(link.getLink().getFromNode().getCoord());
138  Coord linkEndCoord = transform.transform(link.getLink().getToNode().getCoord());
139  Point2D.Double linkStart = new Point2D.Double(linkStartCoord.getX(), linkStartCoord.getY());
140  Point2D.Double linkEnd = new Point2D.Double(linkEndCoord.getX(), linkEndCoord.getY());
141 
142  //calculate length and normal
143  Point2D.Double deltaLink = new Point2D.Double(linkEnd.x - linkStart.x, linkEnd.y - linkStart.y);
144  double euclideanLinkLength = this.calculateEuclideanLinkLength(deltaLink);
145  //calculate the correction factor if real link length is different than euclidean distance
146  double linkLengthCorrectionFactor = euclideanLinkLength / link.getLink().getLength();
147  Point2D.Double deltaLinkNorm = new Point2D.Double(deltaLink.x / euclideanLinkLength, deltaLink.y / euclideanLinkLength);
148  Point2D.Double normalizedOrthogonal = new Point2D.Double(deltaLinkNorm.y, - deltaLinkNorm.x);
149 
150  //first calculate the scale of the link based on the node offset, i.e. the link will be shortened at the beginning and the end
151  double linkScale = 1.0;
152  if ((euclideanLinkLength * 0.2) > (2.0 * nodeOffsetMeter)){ // 2* nodeoffset is more than 20%
153  linkScale = (euclideanLinkLength - (2.0 * nodeOffsetMeter)) / euclideanLinkLength;
154  }
155  else { // use 80 % as euclidean length
156  linkScale = euclideanLinkLength * 0.8 / euclideanLinkLength;
157  }
158 
159  //scale the link
160  Tuple<Double, Double> scaledLink = VectorUtils.scaleVector(linkStart, linkEnd, linkScale);
161  Point2D.Double scaledLinkEnd = scaledLink.getSecond();
162  Point2D.Double scaledLinkStart = scaledLink.getFirst();
163 // log.error("scaledLinkStart: " + scaledLinkStart + " end: " + scaledLinkEnd);
164 
165  VisLinkWLanes lanesLinkData = new VisLinkWLanes(link.getLink().getId().toString());
166  lanesLinkData.setLinkStartEndPoint(scaledLinkStart, scaledLinkEnd);
167  lanesLinkData.setNormalizedLinkVector(deltaLinkNorm);
168  lanesLinkData.setLinkOrthogonalVector(normalizedOrthogonal);
169  lanesLinkData.setNumberOfLanes(link.getLink().getNumberOfLanes());
170 
171  if (lanes != null){
172  int maxAlignment = 0;
173  for (ModelLane lane : lanes){
174  VisLane visLane = this.createVisLane(lane, link.getLink().getLength(), linkScale, linkLengthCorrectionFactor);
175  lanesLinkData.addLaneData(visLane);
176  if (visLane.getAlignment() > maxAlignment) {
177  maxAlignment = visLane.getAlignment();
178  }
179  }
180  lanesLinkData.setMaximalAlignment(maxAlignment);
181 
182  //connect the lanes
183  for (ModelLane lane : lanes){
184  VisLane otfLane = lanesLinkData.getLaneData().get(lane.getLaneData().getId().toString());
185  if (lane.getToLanes() == null || lane.getToLanes().isEmpty()){
186  for (Id<Link> id : lane.getLaneData().getToLinkIds()){
187  otfLane.addToLinkId(id.toString());
188  }
189  }
190  else {
191  for (ModelLane toLane : lane.getToLanes()){
192  VisLane otfToLane = lanesLinkData.getLaneData().get(toLane.getLaneData().getId().toString());
193  otfLane.addToLane(otfToLane);
194  }
195  }
196  }
197  }
198  else {
199  for (Id<Link> id : link.getLink().getToNode().getOutLinks().keySet()){
200  lanesLinkData.addToLinkId(id.toString());
201  }
202  }
203 
204  return lanesLinkData;
205  }
206 
207 
208 
209  private double calculateEuclideanLinkLength(Point2D.Double deltaLink) {
210  return Math.sqrt(Math.pow(deltaLink.x, 2) + Math.pow(deltaLink.y, 2));
211  }
212 
213 }
void setEndPosition(double pos)
Definition: VisLane.java:69
VisLane createVisLane(ModelLane qlane, double linkLength, double linkScale, double linkLengthCorrectionFactor)
Point2D.Double calcPoint(Point2D.Double start, Point2D.Double vector, double distance)
static Tuple< Point2D.Double, Point2D.Double > scaleVector(final Point2D.Double start, final Point2D.Double end, double scaleFactor)
double getNumberOfRepresentedLanes()
void setAlignment(int alignment)
Definition: VisLane.java:87
void setStartPosition(double pos)
Definition: VisLane.java:83
Point2D.Double calculatePointOnLink(final VisLinkWLanes laneLinkData, final double position, final double horizontalFraction)
double getStartsAtMeterFromLinkEnd()
List< ModelLane > getToLanes()
Definition: ModelLane.java:54
Id< Lane > getId()
void addToLinkId(String toLinkId)
Definition: VisLane.java:184
void setNumberOfLanes(double noLanes)
Definition: VisLane.java:99
void connect(Map< String, VisLinkWLanes > otfNetwork)
void addToLane(VisLane toLane)
Definition: VisLane.java:118
VisLinkWLanes createVisLinkLanes(CoordinateTransformation transform, VisLink link, double nodeOffsetMeter, List< ModelLane > lanes)
Map< Id< Link >, ? extends Link > getOutLinks()
double calculateEuclideanLinkLength(Point2D.Double deltaLink)
void recalculatePositions(VisLinkWLanes linkData, SnapshotLinkWidthCalculator linkWidthCalculator)