| | 311 | * Compute center of the circle closest to different nodes. |
| | 312 | * Ensure exact center computation in case nodes are already aligned in circle. |
| | 313 | * |
| | 314 | * This is done by least square method. |
| | 315 | * Let be a_i x + b_i y + c_i = 0 equations of bisectors of each edges. Center must be intersection of all bisectors. |
| | 316 | * [ a1 b1 ] [ -c1 ] |
| | 317 | * With A = [ ... ... ] and Y = [ ... ] |
| | 318 | * [ an bn ] [ -cn ] |
| | 319 | * An approximation of center of circle is (At.A)^-1.At.Y |
| | 320 | * @param nodes Nodes parts of the circle (at least 3) |
| | 321 | * @return An approximation of the center, of null if there is no solution. |
| | 322 | */ |
| | 323 | private EastNorth getCenter(List<Node> nodes) { |
| | 324 | /** |
| | 325 | * Equation of each bisector ax + by + c = 0 |
| | 326 | */ |
| | 327 | int nc = nodes.size(); |
| | 328 | if(nc < 3) return null; |
| | 329 | double[] a = new double[nc]; |
| | 330 | double[] b = new double[nc]; |
| | 331 | double[] c = new double[nc]; |
| | 332 | // Compute equation of bisector |
| | 333 | for(int i = 0; i < nc; i++) { |
| | 334 | EastNorth pt1 = nodes.get(i).getEastNorth(); |
| | 335 | EastNorth pt2 = nodes.get((i+1) % nc).getEastNorth(); |
| | 336 | a[i] = pt1.east() - pt2.east(); |
| | 337 | b[i] = pt1.north() - pt2.north(); |
| | 338 | double d = Math.sqrt(a[i]*a[i] + b[i]*b[i]); |
| | 339 | if(d == 0) return null; |
| | 340 | a[i] /= d; |
| | 341 | b[i] /= d; |
| | 342 | double xC = (pt1.east() + pt2.east()) / 2; |
| | 343 | double yC = (pt1.north() + pt2.north()) / 2; |
| | 344 | c[i] = -(a[i]*xC + b[i]*yC); |
| | 345 | } |
| | 346 | // At.A = [aij] |
| | 347 | double a11 = 0, a12 = 0, a22 = 0; |
| | 348 | // At.Y = [bi] |
| | 349 | double b1 = 0, b2 = 0; |
| | 350 | for(int i = 0; i < nc; i++) { |
| | 351 | a11 += a[i]*a[i]; |
| | 352 | a12 += a[i]*b[i]; |
| | 353 | a22 += b[i]*b[i]; |
| | 354 | b1 -= a[i]*c[i]; |
| | 355 | b2 -= b[i]*c[i]; |
| | 356 | } |
| | 357 | // (At.A)^-1 = [invij] |
| | 358 | double det = a11*a22 - a12*a12; |
| | 359 | if(det == 0) return null; |
| | 360 | double inv11 = a22/det; |
| | 361 | double inv12 = -a12/det; |
| | 362 | double inv22 = a11/det; |
| | 363 | // center (xC, yC) = (At.A)^-1.At.y |
| | 364 | double xC = inv11*b1 + inv12*b2; |
| | 365 | double yC = inv12*b1 + inv22*b2; |
| | 366 | return new EastNorth(xC, yC); |
| | 367 | } |
| | 368 | |
| | 369 | /** |