#10777 closed enhancement (fixed)
[patch] Use a multiplier instead of a fixed "createcircle.nodecount"
Reported by: | Atalanttore | Owned by: | team |
---|---|---|---|
Priority: | normal | Milestone: | 17.09 |
Component: | Core | Version: | latest |
Keywords: | nodecount multiplier circle | Cc: | naoliv, Klumbumbus |
Description
Hi,
I would prefer a multiplier instead of a fixed createcircle.nodecount with a default value of 16. Big circles often need more nodes than 16 and small ones probably less than 16.
My idea is to calculate the necessary nodecount of the circle depending on the distance between the two or three selected nodes for creating a circle.
In short: distance between the selected nodes * multiplier = nodecount
Best Regards,
Ettore Atalan
Attachments (0)
Change History (17)
comment:1 by , 9 years ago
comment:2 by , 9 years ago
Cc: | added |
---|
comment:3 by , 9 years ago
Cc: | added |
---|
comment:4 by , 8 years ago
Empirically I tested the radius value with a (what I consider to be a) satisfactory number of nodes:
r → n 2 → 8 4 → 12 8 → 16 16 → 24 32 → 32 64 → 48
ie, a radius of 16 meters should give us 24 nodes in the circle.
And found a formula that gives a good approximation for this, as 6 * r ^ (1/2)
Of course you will ignore that I don't know Java and consider this as a proof of concept, but I got some very good results by using
numberOfNodesInCircle = (int) Math.ceil(6.0 * Math.pow(r, 0.5));
right after the radius is calculated (at https://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/actions/CreateCircleAction.java#L195)
Is it possible to properly implement this?
comment:6 by , 8 years ago
Functional proof-of-concept patch:
-
src/org/openstreetmap/josm/actions/CreateCircleAction.java
130 130 if (!isEnabled()) 131 131 return; 132 132 133 int numberOfNodesInCircle = Main.pref.getInteger("createcircle.nodecount", 16);134 if (numberOfNodesInCircle < 1) {135 numberOfNodesInCircle = 1;136 } else if (numberOfNodesInCircle > 100) {137 numberOfNodesInCircle = 100;138 }139 140 133 DataSet ds = getLayerManager().getEditDataSet(); 141 134 Collection<OsmPrimitive> sel = ds.getSelected(); 142 135 List<Node> nodes = OsmPrimitive.getFilteredList(sel, Node.class); … … 193 186 double r = Math.sqrt(Math.pow(center.east()-n1.east(), 2) + 194 187 Math.pow(center.north()-n1.north(), 2)); 195 188 189 // minimum circle will have 6 nodes when using a way with length ≥ 1.4m 190 if (r < 0.7) { 191 new Notification( 192 tr("Nodes are too close to create a circle.")) 193 .setIcon(JOptionPane.INFORMATION_MESSAGE) 194 .setDuration(Notification.TIME_LONG) 195 .show(); 196 return; 197 } 198 199 // see #10777 200 int numberOfNodesInCircle = (int) Math.ceil(6.0 * Math.pow(r, 0.5)); 201 196 202 // Order nodes by angle 197 203 PolarNode[] angles = new PolarNode[nodes.size()]; 198 204 for (int i = 0; i < nodes.size(); i++) {
My view: we don't need to have a default value anymore (since it's dynamically calculated using the radius) nor we should create too tiny circles.
comment:7 by , 8 years ago
Summary: | Use a multiplier instead of a fixed "createcircle.nodecount" → [patch] Use a multiplier instead of a fixed "createcircle.nodecount" |
---|
Thanks for the patch! Just two remarks:
- The variable
r
is not in meter. To get a value in meter, you can useLatLon.greatCircleDistance
. - This is a matter of taste, but why not just take a minimum of 6 points, instead of refusing to create a small circle?
comment:8 by , 8 years ago
New version:
-
src/org/openstreetmap/josm/actions/CreateCircleAction.java
130 130 if (!isEnabled()) 131 131 return; 132 132 133 int numberOfNodesInCircle = Main.pref.getInteger("createcircle.nodecount", 16);134 if (numberOfNodesInCircle < 1) {135 numberOfNodesInCircle = 1;136 } else if (numberOfNodesInCircle > 100) {137 numberOfNodesInCircle = 100;138 }139 140 133 DataSet ds = getLayerManager().getEditDataSet(); 141 134 Collection<OsmPrimitive> sel = ds.getSelected(); 142 135 List<Node> nodes = OsmPrimitive.getFilteredList(sel, Node.class); … … 193 186 double r = Math.sqrt(Math.pow(center.east()-n1.east(), 2) + 194 187 Math.pow(center.north()-n1.north(), 2)); 195 188 189 // see #10777 190 LatLon ll1 = Main.getProjection().eastNorth2latlon(n1); 191 LatLon ll2 = Main.getProjection().eastNorth2latlon(center); 192 193 double radiusInMeters = ll1.greatCircleDistance(ll2); 194 195 int numberOfNodesInCircle = (int) Math.ceil(6.0 * Math.pow(radiusInMeters, 0.5)); 196 if (numberOfNodesInCircle < 6) { 197 numberOfNodesInCircle = 6; 198 } 199 196 200 // Order nodes by angle 197 201 PolarNode[] angles = new PolarNode[nodes.size()]; 198 202 for (int i = 0; i < nodes.size(); i++) {
comment:11 by , 8 years ago
Milestone: | → 17.09 |
---|
comment:14 by , 8 years ago
Hi, I wonder if this can be enhanced further to still allow me to dictate the exact number of nodes? I use JOSM to do some local map experiments, but in some cases I wanted to create a circle an exact number of nodes (e.g. 360 or 720). Thanks in advance.
comment:15 by , 8 years ago
You could:
- create a circle at the radius that gives you approxiamtely 360 nodes
- manually delete or add a few nods to match exactly 360
- press
O
to make it a circle again - resize it (
ctrl + alt + mouse move
)
comment:16 by , 8 years ago
Hi Klumbumbus, with all due respect I have a obsession with accuracy. How would the change allow me to ensure that the radius is of an exact value (e.g. 5 km or 10 km)? I like the new way of creating circles, but I also like an advanced mode for exact values. ;-)
comment:17 by , 8 years ago
@ika-chan
Install https://wiki.openstreetmap.org/wiki/JOSM/Plugins/CommandLine and modify the example circle.xml
to allow a higher value in maxvalue
(ie, instead maxvalue="144"
you can set maxvalue="1024"
)
You will be able to specify exactly the radius and number of nodes that you want.
Ticket #12475 has been marked as a duplicate of this ticket.