Ticket #3205: ortho.txt

File ortho.txt, 6.4 KB (added by dmuecke, 3 years ago)
Line 
1Index: src/org/openstreetmap/josm/actions/OrthogonalizeAction.java
2===================================================================
3--- src/org/openstreetmap/josm/actions/OrthogonalizeAction.java (revision 1986)
4+++ src/org/openstreetmap/josm/actions/OrthogonalizeAction.java (working copy)
5@@ -33,6 +33,7 @@
6  * 3. Rotate every edge around its center to align with main orientation or perpendicular to it
7  * 4. Compute new intersection points of two adjascent edges
8  * 5. Move nodes to these points
9+ * 6. if there are nodes between edges then align the nodes
10  */
11 public final class OrthogonalizeAction extends JosmAction {
12 
13@@ -51,8 +52,9 @@
14         Collection<OsmPrimitive> sel = getCurrentDataSet().getSelected();
15 
16         ArrayList<Node> dirnodes = new ArrayList<Node>();
17+        ArrayList<Node> alignNodes = new ArrayList<Node>();
18 
19-        // Check the selection if it is suitible for the orthogonalization
20+        // Check the selection if it is suitable for the orthogonalisation
21         for (OsmPrimitive osm : sel) {
22             // Check if not more than two nodes in the selection
23             if(osm instanceof Node) {
24@@ -104,15 +106,17 @@
25                     delta -= Math.PI;
26                 }
27                 if(delta < Math.PI/4) {
28-                    OptionPaneUtil.showMessageDialog(
29-                            Main.parent,
30-                            tr("Please select ways with almost right angles to orthogonalize."),
31-                            tr("Information"),
32-                            JOptionPane.INFORMATION_MESSAGE
33-                    );
34-                    return;
35+                    // not an edge
36+                    alignNodes.add(way.getNode(i2));
37                 }
38             }
39+
40+            // first node has to be an edge so we move the node to the end of the way
41+            while (alignNodes.contains(way.firstNode())) {
42+                Node n = way.firstNode();
43+                way.removeNode(n);
44+                way.addNode(way.getNodesCount() - 2, n); // ! -2 because first node == last node in closed way
45+            }
46         }
47 
48         if ("EPSG:4326".equals(Main.proj.toString())) {
49@@ -159,12 +163,20 @@
50                 continue;
51             }
52 
53-            Way way = (Way)osm;
54+            Way oldWay = (Way) osm;
55+            Way way = new Way();
56+            // copy only edges into way
57+            for (Node origNode : oldWay.getNodes()) {
58+                if (alignNodes.contains(origNode)) {
59+                    continue;
60+                }
61+                way.addNode(origNode);
62+            }
63             int nodes = way.getNodesCount();
64             int sides = nodes - 1;
65             // Copy necessary data into a more suitable data structure
66             EastNorth en[] = new EastNorth[sides];
67-            for (int i=0; i < sides; i++) {
68+            for (int i = 0; i < sides; i++) {
69                 en[i] = new EastNorth(way.getNode(i).getEastNorth().east(), way.getNode(i).getEastNorth().north());
70             }
71 
72@@ -221,6 +233,12 @@
73                 align_to_heading = normalize_angle(sum_weighted_headings/sum_weights);
74             }
75 
76+            EastNorth aligna = null;
77+            EastNorth alignb = null;
78+            EastNorth align0 = null;
79+            Node nodea = null;
80+            Node nodeb = null;
81+            Node node0 = null;
82 
83             for (int i=0; i < sides; i++) {
84                 // Compute handy indices of three nodes to be used in one loop iteration.
85@@ -276,6 +294,27 @@
86                     double dy = intersection.north()-n.getEastNorth().north();
87                     cmds.add(new MoveCommand(n, dx, dy));
88                 }
89+
90+                // align all nodes between two edges
91+                aligna = alignb;
92+                alignb = intersection;
93+                nodea = nodeb;
94+                nodeb = n;
95+                if (aligna != null) {
96+
97+                    MoveCommand cmd = alignSide(findNodesToAlign(oldWay, nodea, nodeb), aligna, alignb);
98+                    if (cmd != null) {
99+                        cmds.add(cmd);
100+                    }
101+
102+                } else {
103+                    align0 = alignb;
104+                    node0 = nodeb;
105+                }
106+            }
107+            MoveCommand cmd = alignSide(findNodesToAlign(oldWay, nodeb, node0), alignb, align0);
108+            if (cmd != null) {
109+                cmds.add(cmd);
110             }
111         }
112 
113@@ -285,6 +324,62 @@
114         }
115     }
116 
117+    private MoveCommand alignSide(ArrayList<Node> aNodes, EastNorth aligna, EastNorth alignb) {
118+
119+        // Find out co-ords of A and B
120+        double ax = aligna.east();
121+        double ay = aligna.north();
122+        double bx = alignb.east();
123+        double by = alignb.north();
124+
125+        // OK, for each node to move, work out where to move it!
126+        for (Node n1 : aNodes) {
127+            // Get existing co-ords of node to move
128+            double nx = n1.getEastNorth().east();
129+            double ny = n1.getEastNorth().north();
130+
131+            if (ax == bx) {
132+                // Special case if AB is vertical...
133+                nx = ax;
134+            } else if (ay == by) {
135+                // ...or horizontal
136+                ny = ay;
137+            } else {
138+                // Otherwise calculate position by solving y=mx+c
139+                double m1 = (by - ay) / (bx - ax);
140+                double c1 = ay - (ax * m1);
141+                double m2 = (-1) / m1;
142+                double c2 = n1.getEastNorth().north() - (n1.getEastNorth().east() * m2);
143+
144+                nx = (c2 - c1) / (m1 - m2);
145+                ny = (m1 * nx) + c1;
146+            }
147+
148+            // Return the command to move the node to its new position.
149+            return new MoveCommand(n1, nx - n1.getEastNorth().east(), ny - n1.getEastNorth().north());
150+        }
151+        return null;
152+    }
153+
154+    private ArrayList<Node> findNodesToAlign(Way w, Node from, Node to) {
155+        ArrayList<Node> l = new ArrayList<Node>();
156+        boolean start = false;
157+        for (int i = 0; i < w.getNodesCount(); i++) {
158+            Node n = w.getNode(i % w.getNodesCount());
159+            if (n.equals(to)) {
160+                break;
161+            }
162+            if (start) {
163+                l.add(n);
164+            }
165+            if (n.equals(from)) {
166+                start = true;
167+            }
168+
169+        }
170+        return l;
171+    }
172+
173     static double det(double a, double b, double c, double d)
174     {
175         return a * d - b * c;