Changeset 25007 in osm for applications
- Timestamp:
- 2011-01-09T13:49:23+01:00 (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/simplifyarea/src/sk/zdila/josm/plugin/simplify/SimplifyAreaAction.java
r24846 r25007 10 10 import java.awt.event.ActionEvent; 11 11 import java.awt.event.KeyEvent; 12 import java.util.ArrayList;13 12 import java.util.Collection; 13 import java.util.HashMap; 14 14 import java.util.HashSet; 15 15 import java.util.LinkedList; 16 16 import java.util.List; 17 import java.util.Map; 17 18 18 19 import javax.swing.JOptionPane; … … 168 169 */ 169 170 private SequenceCommand simplifyWay(final Way w) { 170 final double angleThreshold = Main.pref.getDouble("simplify-area.angle", 10); 171 final double mergeThreshold = Main.pref.getDouble("simplify-area.merge", 0.2); 172 final double areaThreshold = Main.pref.getDouble("simplify-area.area", 5.0); 173 final double distanceThreshold = Main.pref.getDouble("simplify-area.dist", 3); 171 final double angleThreshold = Main.pref.getDouble("simplify-area.angle.threshold", 10); 172 final double angleFactor = Main.pref.getDouble("simplify-area.angle.factor", 1.0); 173 final double mergeThreshold = Main.pref.getDouble("simplify-area.merge.threshold", 0.2); 174 final double areaThreshold = Main.pref.getDouble("simplify-area.area.threshold", 5.0); 175 final double areaFactor = Main.pref.getDouble("simplify-area.area.factor", 1.0); 176 final double distanceThreshold = Main.pref.getDouble("simplify-area.dist.threshold", 3); 177 final double distanceFactor = Main.pref.getDouble("simplify-area.dist.factor", 3); 174 178 175 179 final List<Node> nodes = w.getNodes(); … … 180 184 } 181 185 182 final List<MoveCommand> moveCommandList = new ArrayList<MoveCommand>();183 184 186 final boolean closed = nodes.get(0).equals(nodes.get(size - 1)); 185 186 final List<Node> newNodes = new ArrayList<Node>(size);187 187 188 188 if (closed) { … … 190 190 } 191 191 192 // remove near nodes 193 for (int i = 0; i < size; i++) { 194 final boolean closing = closed && i == size - 1; 195 final Node n1 = closing ? nodes.get(0) : nodes.get(i); 196 197 if (newNodes.isEmpty()) { 198 newNodes.add(n1); 199 continue; 200 } 201 202 final Node n2 = newNodes.get(newNodes.size() - 1); 203 204 final LatLon coord1 = n1.getCoor(); 205 final LatLon coord2 = n2.getCoor(); 206 207 if (isRequiredNode(w, n1) || isRequiredNode(w, n2) || coord1.greatCircleDistance(coord2) > mergeThreshold) { 208 if (!closing) { 209 newNodes.add(n1); 210 } 211 } else { 212 moveCommandList.add(new MoveCommand(n2, coord1.getCenter(coord2))); 213 if (closing) { 214 newNodes.remove(0); 215 } 216 } 217 } 218 219 final int size2 = newNodes.size(); 220 221 final List<Node> newNodes2 = new ArrayList<Node>(size2); 222 223 Node prevNode = null; 224 LatLon coord1 = null; 225 LatLon coord2 = null; 226 227 for (int i = 0, j = 0, len = size2 + (closed ? 2 : 1); i < len; i++, j++) { 228 final Node n = newNodes.get(j % newNodes.size()); 229 final LatLon coord3 = n.getCoor(); 230 231 if (coord1 != null) { 232 // System.out.print("AREA: " + computeArea(coord1, coord2, coord3) + "; ANGLE: " + computeConvectAngle(coord1, coord2, coord3) + "; XTE: " + crossTrackError(coord1, coord2, coord3)); 233 234 // final double weight = isRequiredNode(w, prevNode) || !closed && i == len - 1 ? Double.MAX_VALUE : 235 // computeConvectAngle(coord1, coord2, coord3) / angleThreshold + 236 // computeArea(coord1, coord2, coord3) / areaThreshold + 237 // Math.abs(crossTrackError(coord1, coord2, coord3)) / distanceThreshold; 238 239 if (isRequiredNode(w, prevNode) || 240 !closed && i == len - 1 || // don't remove last node of the not closed way 241 computeConvectAngle(coord1, coord2, coord3) > angleThreshold || 242 computeArea(coord1, coord2, coord3) > areaThreshold || 243 Math.abs(crossTrackError(coord1, coord2, coord3)) > distanceThreshold) { 244 newNodes2.add(prevNode); 245 // System.out.println(" ... KEEP " + prevNode.getUniqueId()); 246 } else { 247 // System.out.println(" ... REMOVE " + prevNode.getUniqueId()); 248 coord2 = coord1; // at the end of the iteration preserve coord1 249 newNodes.remove(prevNode); 250 j--; 251 } 252 } else if (!closed && prevNode != null) { 253 newNodes2.add(prevNode); 254 } 255 256 coord1 = coord2; 257 coord2 = coord3; 258 prevNode = n; 259 } 192 // remove nodes within threshold 193 194 while (true) { 195 Node prevNode = null; 196 LatLon coord1 = null; 197 LatLon coord2 = null; 198 199 double minWeight = Double.MAX_VALUE; 200 Node bestMatch = null; 201 202 for (int i = 0, len = nodes.size() + (closed ? 2 : 1); i < len; i++) { 203 final Node n = nodes.get(i % nodes.size()); 204 final LatLon coord3 = n.getCoor(); 205 206 if (coord1 != null) { 207 final double angleWeight = computeConvectAngle(coord1, coord2, coord3) / angleThreshold; 208 final double areaWeight = computeArea(coord1, coord2, coord3) / areaThreshold; 209 final double distanceWeight = Math.abs(crossTrackError(coord1, coord2, coord3)) / distanceThreshold; 210 211 final double weight = isRequiredNode(w, prevNode) || 212 !closed && i == len - 1 || // don't remove last node of the not closed way 213 angleWeight > 1.0 || areaWeight > 1.0 || distanceWeight > 1.0 ? Double.MAX_VALUE : 214 angleWeight * angleFactor + areaWeight * areaFactor + distanceWeight * distanceFactor; 215 216 if (weight < minWeight) { 217 minWeight = weight; 218 bestMatch = prevNode; 219 } 220 } 221 222 coord1 = coord2; 223 coord2 = coord3; 224 prevNode = n; 225 } 226 227 if (bestMatch == null) { 228 break; 229 } 230 231 nodes.remove(bestMatch); 232 } 233 234 235 // average nearby nodes 236 237 final Map<Node, LatLon> coordMap = new HashMap<Node, LatLon>(); 238 for (final Node n : nodes) { 239 coordMap.put(n, n.getCoor()); 240 } 241 242 final Map<Node, MoveCommand> moveCommandList = new HashMap<Node, MoveCommand>(); 243 244 while (true) { 245 double minDist = Double.MAX_VALUE; 246 Node node1 = null; 247 Node node2 = null; 248 249 for (int i = 0, len = nodes.size() + (closed ? 2 : 1); i < len; i++) { 250 final Node n1 = nodes.get(i % nodes.size()); 251 final Node n2 = nodes.get((i + 1) % nodes.size()); 252 253 if (isRequiredNode(w, n1) || isRequiredNode(w, n2)) { 254 continue; 255 } 256 257 final double dist = coordMap.get(n1).greatCircleDistance(coordMap.get(n2)); 258 if (dist < minDist && dist < mergeThreshold) { 259 minDist = dist; 260 node1 = n1; 261 node2 = n2; 262 } 263 } 264 265 if (node1 == null || node2 == null) { 266 break; 267 } 268 269 270 final LatLon coord = coordMap.get(node1).getCenter(coordMap.get(node2)); 271 coordMap.put(node1, coord); 272 moveCommandList.put(node1, new MoveCommand(node1, coord)); 273 274 nodes.remove(node2); 275 coordMap.remove(node2); 276 moveCommandList.remove(node2); 277 } 278 260 279 261 280 if (closed) { 262 newNodes2.add(newNodes2.get(0)); // set end node ( = start node) 263 } 264 265 final HashSet<Node> delNodes = new HashSet<Node>(); 266 delNodes.addAll(nodes); 267 delNodes.removeAll(newNodes2); 281 nodes.add(nodes.get(0)); // set end node ( = start node) 282 } 283 284 final HashSet<Node> delNodes = new HashSet<Node>(w.getNodes()); 285 delNodes.removeAll(nodes); 268 286 269 287 if (delNodes.isEmpty()) { … … 273 291 final Collection<Command> cmds = new LinkedList<Command>(); 274 292 final Way newWay = new Way(w); 275 newWay.setNodes(n ewNodes2);276 277 cmds.addAll(moveCommandList );293 newWay.setNodes(nodes); 294 295 cmds.addAll(moveCommandList.values()); 278 296 cmds.add(new ChangeCommand(w, newWay)); 279 297 cmds.add(new DeleteCommand(delNodes)); … … 295 313 final double p = (a + b + c) / 2.0; 296 314 297 return Math.sqrt(p * (p - a) * (p - b) * (p - c)); 315 final double q = p * (p - a) * (p - b) * (p - c); // I found this negative in one case (:-o) when nodes were in line on a small area 316 return q < 0.0 ? 0.0 : Math.sqrt(q); 298 317 } 299 318
Note:
See TracChangeset
for help on using the changeset viewer.