Changeset 27588 in osm for applications
- Timestamp:
- 2012-01-22T23:22:56+01:00 (13 years ago)
- Location:
- applications/editors/josm/plugins/alignways/src/com/tilusnet/josm/plugins/alignways
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/alignways/src/com/tilusnet/josm/plugins/alignways/AlignWaysCmdKeepAngles.java
r27353 r27588 34 34 35 35 // Now the calculatedNodes reflect the coordinates that we'd have 36 // without preserving the angles .36 // without preserving the angles, i.e. preserving the length. 37 37 38 38 Map<Node,EastNorth> calcNodesKeepLength = calculatedNodes; 39 39 40 // Now we'll proceed with the hypothetical recalculation of the endpoint coordinates 41 // following the rule of preserving angles instead. The new nodes will be stored in nodeArr[]. 42 40 43 Node[] nodeArr = algnSeg.getSegmentEndPoints().toArray(new Node[2]); 41 44 … … 44 47 AlignWaysGeomLine lineKeepLength = new AlignWaysGeomLine(enCalc1.getX(), enCalc1.getY(), enCalc2.getX(), enCalc2.getY()); 45 48 46 recalculateNodes(lineKeepLength, nodeArr[0]); 47 recalculateNodes(lineKeepLength, nodeArr[1]); 48 49 } 50 51 52 void recalculateNodes(AlignWaysGeomLine alignedLineKeepLength, Node endpoint) { 53 49 recalculateNodesAndValidate(lineKeepLength, nodeArr[0]); 50 recalculateNodesAndValidate(lineKeepLength, nodeArr[1]); 51 52 } 53 54 55 void recalculateNodesAndValidate(AlignWaysGeomLine alignedLineKeepLength, Node endpoint) { 56 57 if (endpoint.getEastNorth().equals(pivot)) { 58 // endpoint is pivot: the coordinates won't change 59 return; 60 } 61 54 62 ArrayList<WaySegment> alws = algnSeg.getAdjacentWaySegments(endpoint); 55 if (alws.size() == 1) {63 if (alws.size() <= 2) { 56 64 // We need the intersection point of 57 // - the freely rotated alignee as calculated in calcNodesFreeAngle65 // - the alignee following the keep length rule 58 66 // - the adjacent way segment 59 60 EastNorth enAdj1 = alws.get(0).getFirstNode().getEastNorth(); 61 EastNorth enAdj2 = alws.get(0).getSecondNode().getEastNorth(); 62 63 // Update the calculated node for aligning while keeping angles 64 AlignWaysGeomPoint isectPnt = alignedLineKeepLength.getIntersection(new AlignWaysGeomLine(enAdj1.getX(), enAdj1.getY(), enAdj2.getX(), enAdj2.getY())); 67 68 EastNorth enAdjOther1 = getNonEqualEN(alws.get(0), endpoint); 69 EastNorth enAdjOther2 = null; 70 71 if (alws.size() == 2) { 72 enAdjOther2 = getNonEqualEN(alws.get(1), endpoint); 73 74 // In order have a chance to align, (enAdjOther1, enAdjOther2 and endpoint) must be collinear 75 ArrayList<EastNorth> enAdjPts = new ArrayList<EastNorth>(3); 76 enAdjPts.add(enAdjOther1); 77 enAdjPts.add(endpoint.getEastNorth()); 78 enAdjPts.add(enAdjOther2); 79 if (!isEnSetCollinear(enAdjPts)) { 80 // Not collinear, no point to proceed 81 alignableStatKeepAngles = AlignableStatus.ALGN_INV_ANGLE_PRESERVING_CONFLICT; 82 return; 83 } 84 85 } 86 87 // Update the calculated node for angle preserving alignment 88 AlignWaysGeomPoint isectPnt = alignedLineKeepLength.getIntersection(new AlignWaysGeomLine(enAdjOther1.getX(), enAdjOther1.getY(), 89 endpoint.getEastNorth().getX(), endpoint.getEastNorth().getY())); 90 EastNorth enIsectPt = null; 65 91 // If the intersection is null, the adjacent and the alignee are parallel already: 66 92 // there's no need to update this node 67 93 if (isectPnt != null) { 68 calculatedNodes.put(endpoint, new EastNorth(isectPnt.getX(), isectPnt.getY())); 94 enIsectPt = new EastNorth(isectPnt.getX(), isectPnt.getY()); 95 calculatedNodes.put(endpoint, enIsectPt); 69 96 } else if (alignedLineKeepLength.getIntersectionStatus() == IntersectionStatus.LINES_PARALLEL) { 70 97 alignableStatKeepAngles = AlignableStatus.ALGN_INV_ANGLE_PRESERVING_CONFLICT; 71 98 } 99 100 // For the case of two adjacent segments with collinear points, the new endpoint may 101 // not fall between enAdjOther1 and enAdjOther2; in this case one of them is redundant 102 // and should be deleted from OSM 103 if (alws.size() == 2 && enIsectPt != null) { 104 int middlePtIdx = AlignWaysGeomPoint.getMiddleOf3( 105 new AlignWaysGeomPoint(enIsectPt), 106 new AlignWaysGeomPoint(enAdjOther1), 107 new AlignWaysGeomPoint(enAdjOther2)); 108 if (middlePtIdx != 0) { 109 EastNorth middlePt = null; 110 switch(middlePtIdx) { 111 case 1: 112 middlePt = enIsectPt; 113 break; 114 case 2: 115 middlePt = enAdjOther1; 116 break; 117 case 3: 118 middlePt = enAdjOther2; 119 break; 120 } 121 if (middlePt != null) { 122 double eps = 1E-6; 123 if (!middlePt.equalsEpsilon(enIsectPt, eps)) { 124 // Intersection point didn't fall between the two adjacent points; something must go 125 if (middlePt.equalsEpsilon(enAdjOther1, eps)) { 126 // TODO Delete enAdjOther1 127 if (true); 128 // Main.map. 129 } else 130 // TODO Delete enAdjOther2 131 if (true); 132 } 133 } 134 } 135 } 136 72 137 } else { 73 if (!endpoint.getEastNorth().equals(pivot)) { 74 // Report non-pivot endpoints only 75 alignableStatKeepAngles = AlignableStatus.ALGN_INV_TOOMANY_CONNECTED_WS; 76 } 138 // angle preserving alignment not possible 139 alignableStatKeepAngles = AlignableStatus.ALGN_INV_TOOMANY_CONNECTED_WS; 77 140 } 78 141 … … 80 143 81 144 82 /** 145 private boolean isEnSetCollinear(ArrayList<EastNorth> enAdjPts) { 146 ArrayList<AlignWaysGeomPoint> awAdjPts = new ArrayList<AlignWaysGeomPoint>(); 147 148 for (EastNorth en : enAdjPts) { 149 AlignWaysGeomPoint pt = new AlignWaysGeomPoint(en.getX(), en.getY()); 150 awAdjPts.add(pt); 151 } 152 153 return AlignWaysGeomPoint.isSetCollinear(awAdjPts); 154 } 155 156 157 private EastNorth getNonEqualEN(WaySegment waySegment, Node endpoint) { 158 if (waySegment.getFirstNode().equals(endpoint)) { 159 return waySegment.getSecondNode().getEastNorth(); 160 } else if (waySegment.getSecondNode().equals(endpoint)) { 161 return waySegment.getFirstNode().getEastNorth(); 162 } else 163 return null; 164 } 165 166 167 /** 83 168 * Reports invalid alignable statuses on screen in dialog boxes. 84 169 * … … 140 225 return status; 141 226 142 // Check the remainder of the potential problems: - 143 // Check for the number of segments connecting to the alignee endpoints 144 for (Node nA : displaceableNodes) { 145 if (nA.getEastNorth().equals(pivot)) { 146 // Pivots set to endpoints are exempt from this check 147 continue; 148 } else { 149 // This node should not connect to more than one other way segment 150 if (isReferredByNOtherWaySegments(nA, 2)) 151 return AlignableStatus.ALGN_INV_TOOMANY_CONNECTED_WS; 152 } 153 } 227 // Check the remainder of the potential problems: N/A 154 228 155 229 // In all other cases alignment is possible -
applications/editors/josm/plugins/alignways/src/com/tilusnet/josm/plugins/alignways/geometry/AlignWaysGeomLine.java
r27348 r27588 75 75 } 76 76 77 /** 78 * Returns the intersection point the line with another line. 77 public AlignWaysGeomLine(AlignWaysGeomPoint awPt1, AlignWaysGeomPoint awPt2) { 78 this(awPt1.getX(), awPt1.getY(), awPt2.getX(), awPt2.getY()); 79 } 80 81 /** 82 * Returns the intersection point of the line with another line. 79 83 * If the lines are parallel or overlap, returns null. 80 84 * Use getIntersectionStatus() to determine the case. … … 180 184 } 181 185 186 public boolean isPointOnLine(AlignWaysGeomPoint awPt) { 187 // Method: 188 // 1. create a new line from awPt and one point of 'this' 189 // 2. check getIntersectionStatus of the two lines 190 // 3. if status is LINES_OVERLAP, the point os one the line, otherwise not 191 192 // Need an arbitrary point on this line; let it be (x, y) 193 Double x = 0.0; 194 Double y = getYonLine(x); 195 if (y.isNaN()) y = 0.0; 196 197 AlignWaysGeomLine line2 = new AlignWaysGeomLine(awPt, new AlignWaysGeomPoint(x, y)); 198 getIntersection(line2); 199 if (getIntersectionStatus() == IntersectionStatus.LINES_OVERLAP) 200 return true; 201 else 202 return false; 203 204 } 205 182 206 } -
applications/editors/josm/plugins/alignways/src/com/tilusnet/josm/plugins/alignways/geometry/AlignWaysGeomPoint.java
r27348 r27588 1 1 package com.tilusnet.josm.plugins.alignways.geometry; 2 3 import java.util.ArrayList; 4 import java.util.Arrays; 5 import java.util.Collections; 6 7 import org.openstreetmap.josm.data.coor.EastNorth; 2 8 3 9 public class AlignWaysGeomPoint { … … 10 16 } 11 17 12 public double getX() { 18 public AlignWaysGeomPoint(EastNorth eastNorth) { 19 this.x = eastNorth.getX(); 20 this.y = eastNorth.getY(); 21 } 22 23 public double getX() { 13 24 return x; 14 25 } … … 26 37 } 27 38 39 public static boolean isSetCollinear(ArrayList<AlignWaysGeomPoint> awPts) { 40 if (awPts.size() <= 1) 41 return false; 42 43 if (awPts.size() == 2) 44 return true; 45 else { 46 // at least 3 points 47 // First create a line of the first two points in the set 48 AlignWaysGeomLine line = new AlignWaysGeomLine(awPts.get(0), awPts.get(1)); 49 // ...then check the subsequent points whether they are on the line 50 for (int i = 2; i < awPts.size(); i++) { 51 if (!line.isPointOnLine(awPts.get(i))) { 52 return false; 53 } 54 } 55 return true; 56 } 57 } 58 59 /** 60 * Determines which (EastNorth) point falls between the other two. 61 * Ideally to be used with collinear points. 62 * 63 * @return 1, 2 or 3 for pt1, pt2 and pt3, respectively. 64 * 0 if middle value cannot be determined (i.e. some values are equal). 65 */ 66 public static int getMiddleOf3( 67 AlignWaysGeomPoint pt1, 68 AlignWaysGeomPoint pt2, 69 AlignWaysGeomPoint pt3) { 70 71 int midPtXIdx = getMiddleOf3(pt1.x, pt2.x, pt3.x); 72 int midPtYIdx = getMiddleOf3(pt1.y, pt2.y, pt3.y); 73 74 if ((midPtXIdx == 0) && (midPtYIdx == 0)) 75 // All 3 points overlap: 76 // Design decision: return the middle point (could be any other or none) 77 return 2; 78 79 if (midPtXIdx == 0) return midPtYIdx; 80 if (midPtYIdx == 0) return midPtXIdx; 81 82 // Both x and y middle points could be determined; 83 // their indexes must coincide 84 if (midPtXIdx == midPtYIdx) 85 // Success 86 return midPtXIdx; // (or midPtYIdx) 87 else 88 // Fail 89 return 0; 90 91 } 92 93 /** 94 * Determine which value, d1, d2 or d3 falls in the middle of the other two. 95 * @return 1, 2 or 3 for d1, d2 and d3, respectively. 96 * 0 if middle value cannot be determined (i.e. some values are equal). 97 */ 98 private static int getMiddleOf3(double d1, double d2, double d3) { 99 100 Double[] dValues = {d1, d2, d3}; 101 ArrayList<Double> alValues = new ArrayList<Double>(Arrays.asList(dValues)); 102 Collections.sort(alValues); 103 104 if ((Math.abs(alValues.get(1) - alValues.get(0)) < 0.01) || 105 (Math.abs(alValues.get(1) - alValues.get(2)) < 0.01)) 106 // Cannot determine absolute middle value 107 return 0; 108 else { 109 if (Math.abs(alValues.get(1) - d1) < 0.01) return 1; 110 if (Math.abs(alValues.get(1) - d2) < 0.01) return 2; 111 if (Math.abs(alValues.get(1) - d3) < 0.01) return 3; 112 } 113 114 // Should never happen 115 return 0; 116 } 28 117 }
Note:
See TracChangeset
for help on using the changeset viewer.