Changeset 1768 in josm


Ignore:
Timestamp:
2009-07-11T15:37:10+02:00 (15 years ago)
Author:
stoecker
Message:

close #2781 - patch by Landwirt - fix align in circle

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/AlignInCircleAction.java

    r1713 r1768  
    66import java.awt.event.ActionEvent;
    77import java.awt.event.KeyEvent;
     8import java.math.BigDecimal;
     9import java.math.MathContext;
    810import java.util.Collection;
    911import java.util.LinkedList;
     
    3537    }
    3638
    37     public double determinant(double[][] mat) {
    38         double result = 0;
    39 
    40         if (mat.length == 1) {
    41             result = mat[0][0];
    42             return result;
    43         }
    44 
    45         if (mat.length == 2) {
    46             result = mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0];
    47             return result;
    48         }
    49 
    50         for (int i = 0; i < mat[0].length; i++) {
    51             double temp[][] = new double[mat.length - 1][mat[0].length - 1];
    52             for (int j = 1; j < mat.length; j++) {
    53                 for (int k = 0; k < mat[0].length; k++) {
    54                     if (k < i) {
    55                         temp[j - 1][k] = mat[j][k];
    56                     } else if (k > i) {
    57                         temp[j - 1][k - 1] = mat[j][k];
    58                     }
    59                 }
    60             }
    61             result += mat[0][i] * Math.pow(-1, i) * determinant(temp);
    62         }
    63         return result;
    64     }
    65 
    6639    public double distance(EastNorth n, EastNorth m) {
    6740        double easd, nord;
     
    6942        nord = n.north() - m.north();
    7043        return Math.sqrt(easd * easd + nord * nord);
    71     }
    72 
    73     public EastNorth circumcenter(EastNorth i, EastNorth j, EastNorth k) {
    74         // move to 0,0, to eliminate numeric errors
    75         double ie = i.east() - i.east();
    76         double in = i.north() - i.north();
    77         double je = j.east() - i.east();
    78         double jn = j.north() - i.north();
    79         double ke = k.east() - i.east();
    80         double kn = k.north() - i.north();
    81         double[][] ma = { { ie, in, 1 }, { je, jn, 1 }, { ke, kn, 1 } };
    82         double[][] mbx = { { (ie * ie + in * in), in, 1 }, { (je * je + jn * jn), jn, 1 },
    83                 { (ke * ke + kn * kn), kn, 1 } };
    84         double[][] mby = { { ie * ie + in * in, ie, 1 }, { je * je + jn * jn, je, 1 }, { ke * ke + kn * kn, ke, 1 } };
    85         double a = determinant(ma);
    86         double bx = determinant(mbx);
    87         double by = determinant(mby);
    88         EastNorth result = new EastNorth(bx / (2 * a) + i.east(), -by / (2 * a) + i.north());
    89 
    90         Node n = new Node(Main.proj.eastNorth2latlon(result));
    91         if (n.getCoor().isOutSideWorld()) {
    92             JOptionPane.showMessageDialog(Main.parent, tr("Some of the nodes are (almost) in the line"));
    93             return null;
    94         }
    95         return result;
    9644    }
    9745
     
    13987
    14088        for (OsmPrimitive osm : sel) {
    141             if (osm instanceof Node)
     89            if (osm instanceof Node) {
    14290                nodes.add((Node) osm);
    143             else if (osm instanceof Way)
     91            } else if (osm instanceof Way) {
    14492                ways.add((Way) osm);
     93            }
    14594        }
    14695
     
    164113
    165114                    center = ((Node) nodes.toArray()[way.nodes.contains(nodes.toArray()[0]) ? 1 : 0]).getEastNorth();
    166                     if (nodes.size() == 2)
     115                    if (nodes.size() == 2) {
    167116                        radius = distance(((Node) nodes.toArray()[0]).getEastNorth(), ((Node) nodes.toArray()[1]).getEastNorth());
     117                    }
    168118                }
    169119                nodes = new LinkedList<Node>();
     
    171121
    172122            for (Node n : way.nodes) {
    173                 if (!nodes.contains(n))
     123                if (!nodes.contains(n)) {
    174124                    nodes.add(n);
     125                }
    175126            }
    176127        }
     
    181132        }
    182133
    183         // Get average position of circumcircles of the triangles of all triplets of neighbour nodes
    184134        if (center == null) {
    185 
    186135            // Compute the centroid of nodes
    187136
     137            BigDecimal area = new BigDecimal("0");
     138            BigDecimal north = new BigDecimal("0");
     139            BigDecimal east = new BigDecimal("0");
     140
    188141            // See http://en.wikipedia.org/w/index.php?title=Centroid&oldid=294224857#Centroid_of_polygon for the equation used here
    189             double area = 0;
    190             double north = 0;
    191             double east = 0;
    192 
    193             // Integrate the area, east and north centroid, we'll compute the final value based on the result of integration
    194             for (int i=0; i<nodes.size(); i++) {
     142            for (int i = 0; i < nodes.size(); i++) {
    195143                EastNorth n0 = ((Node) nodes.toArray()[i]).getEastNorth();
    196144                EastNorth n1 = ((Node) nodes.toArray()[(i+1) % nodes.size()]).getEastNorth();
    197145
    198                 area  += n0.east()*n1.north()-n1.east()*n0.north();
    199                 east  += (n0.east() +n1.east()) *(n0.east()*n1.north()-n1.east()*n0.north());
    200                 north += (n0.north()+n1.north())*(n0.east()*n1.north()-n1.east()*n0.north());
    201             }
    202             area  /= 2;
    203             north /= 6*area;
    204             east  /= 6*area;
    205             center = new EastNorth(east, north);
    206         }
    207 
     146                BigDecimal x0 = new BigDecimal(n0.east());
     147                BigDecimal y0 = new BigDecimal(n0.north());
     148                BigDecimal x1 = new BigDecimal(n1.east());
     149                BigDecimal y1 = new BigDecimal(n1.north());
     150
     151                BigDecimal k = x0.multiply(y1, MathContext.DECIMAL128).subtract(y0.multiply(x1, MathContext.DECIMAL128));
     152
     153                area = area.add(k, MathContext.DECIMAL128);
     154                east = east.add(k.multiply(x0.add(x1, MathContext.DECIMAL128), MathContext.DECIMAL128));
     155                north = north.add(k.multiply(y0.add(y1, MathContext.DECIMAL128), MathContext.DECIMAL128));
     156
     157            }
     158
     159            BigDecimal d = new BigDecimal("2");
     160            area  = area.divide(d, MathContext.DECIMAL128);
     161            d = new BigDecimal("6");
     162            north = north.divide(d.multiply(area, MathContext.DECIMAL128), MathContext.DECIMAL128);
     163            east = east.divide(d.multiply(area, MathContext.DECIMAL128), MathContext.DECIMAL128);
     164
     165            center = new EastNorth(east.doubleValue(), north.doubleValue());
     166
     167        }
    208168        // Node "center" now is central to all selected nodes.
    209169
     
    226186            pc = new PolarCoor(((Node) nodes.toArray()[0]).getEastNorth(), center, 0);
    227187
    228             if (pc.angle > (new PolarCoor(((Node) nodes.toArray()[1]).getEastNorth(), center, 0).angle))
     188            if (pc.angle > (new PolarCoor(((Node) nodes.toArray()[1]).getEastNorth(), center, 0).angle)) {
    229189                angle *= -1;
     190            }
    230191
    231192            pc.radius = radius;
Note: See TracChangeset for help on using the changeset viewer.