de65914f43
- modifiche per integrare vroni con le nostre librerie - spostamento header in Extern per evitare duplicati.
713 lines
28 KiB
C++
713 lines
28 KiB
C++
/*****************************************************************************/
|
|
/* */
|
|
/* Copyright (C) 2007-2023 S. Huber, M. Held */
|
|
/* */
|
|
/* This code is not in the public domain. All rights reserved! Please make */
|
|
/* sure to read the full copyright statement contained in "README.txt" or in */
|
|
/* the "main" file of this code, such as "main.cc". */
|
|
/* */
|
|
/*****************************************************************************/
|
|
/* */
|
|
/* Written by: Stefan Huber, Martin Held */
|
|
/* */
|
|
/* E-Mail: held@cs.sbg.ac.at */
|
|
/* Fax Mail: (+43 662) 8044-611 */
|
|
/* Voice Mail: (+43 662) 8044-6304 */
|
|
/* Snail Mail: Martin Held */
|
|
/* FB Informatik */
|
|
/* Universitaet Salzburg */
|
|
/* A-5020 Salzburg, Austria */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
/* */
|
|
/* get standard libraries */
|
|
/* */
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <float.h>
|
|
|
|
/* */
|
|
/* get my header files */
|
|
/* */
|
|
#include "vroni_object.h"
|
|
#include "vronivector.h"
|
|
#include "fpkernel.h"
|
|
#include "defs.h"
|
|
#include "numerics.h"
|
|
#include "roots.h"
|
|
#include "vddata.h"
|
|
|
|
|
|
|
|
/* */
|
|
/* Calculate the Voronoi center of three arcs */
|
|
/* */
|
|
vr_bool vroniObject::ArcArcArcCntr(int i, int j, int k, int e,
|
|
coord* cntr, double *r2,
|
|
vr_bool *problematic, int *site)
|
|
{
|
|
int t, m, n, best_sol, n1;
|
|
coord c1, c2, c3;
|
|
double rr1, rr2, rr3, rad;
|
|
coord centers[VRONI_MAXSOL];
|
|
double radii[VRONI_MAXSOL];
|
|
int num_sol=0;
|
|
coord tmp;
|
|
int tmpi;
|
|
double tmpr;
|
|
coord spi, epi, spj, epj, spk, epk;
|
|
double eps;
|
|
int i_in, j_in, k_in;
|
|
vr_bool ik_joint = false, jk_joint = false, ij_joint = false, no_check;
|
|
vr_bool ik_tangent = false, jk_tangent = false, ij_tangent = false, is_special;
|
|
vr_bool jk_counter = false, ij_counter = false, ik_counter = false;
|
|
double d_c1c2, d_c1c3, d_c2c3;
|
|
coord ep, v;
|
|
|
|
#ifdef TRACE
|
|
if ((i == 0) && (j == 1) && (k == 23)) {
|
|
printf("arc %d-arc %d-arc %d\n", i, j, k);
|
|
printf("start1 : (%20.16f %20.16f)\n", GetArcStartCoord(i).x,
|
|
GetArcStartCoord(i).y);
|
|
printf("end1 : (%20.16f %20.16f)\n", GetArcEndCoord(i).x,
|
|
GetArcEndCoord(i).y);
|
|
printf("center1: (%20.16f %20.16f)\n", GetArcCenter(i).x,
|
|
GetArcCenter(i).y);
|
|
printf("start2 : (%20.16f %20.16f)\n", GetArcStartCoord(j).x,
|
|
GetArcStartCoord(j).y);
|
|
printf("end2 : (%20.16f %20.16f)\n", GetArcEndCoord(j).x,
|
|
GetArcEndCoord(j).y);
|
|
printf("center2: (%20.16f %20.16f)\n", GetArcCenter(j).x,
|
|
GetArcCenter(j).y);
|
|
printf("start3 : (%20.16f %20.16f)\n", GetArcStartCoord(k).x,
|
|
GetArcStartCoord(k).y);
|
|
printf("end3 : (%20.16f %20.16f)\n", GetArcEndCoord(k).x,
|
|
GetArcEndCoord(k).y);
|
|
printf("center3: (%20.16f %20.16f)\n", GetArcCenter(k).x,
|
|
GetArcCenter(k).y);
|
|
}
|
|
#endif
|
|
|
|
i_in = i;
|
|
j_in = j;
|
|
k_in = k;
|
|
|
|
*site = NIL;
|
|
*problematic = false;
|
|
|
|
/* */
|
|
/* Guarantee that permutations of i,j,k lead to same center */
|
|
/* */
|
|
SortThreeNumbers(i,j,k,t);
|
|
|
|
/* */
|
|
/* Check whether the three cites are all in lists */
|
|
/* */
|
|
assert(InArcsList(i));
|
|
assert(InArcsList(j));
|
|
assert(InArcsList(k));
|
|
|
|
/* */
|
|
/* check whether the three sites share a common end point, or whether two */
|
|
/* of them are identical */
|
|
/* */
|
|
eps = GetIntersectionThreshold();
|
|
m = Get1stVtx(k, ARC);
|
|
if (IsArcStartPnt(i, m) || IsArcEndPnt(i, m)) {
|
|
if (IsArcStartPnt(j, m) || IsArcEndPnt(j, m)) {
|
|
n = Get2ndVtx(k, ARC);
|
|
if (IsArcStartPnt(i, n) || IsArcEndPnt(i, n)) {
|
|
if (le(PntPntDist(GetArcCenter(i),GetArcCenter(k)), eps)) {
|
|
SetInvalidSites(i, ARC, k, ARC, eps);
|
|
restart = false;
|
|
return false; /* duplicate arcs ! */
|
|
}
|
|
}
|
|
else if (IsArcStartPnt(j, n) || IsArcEndPnt(j, n)) {
|
|
if (le(PntPntDist(GetArcCenter(j),GetArcCenter(k)), eps)) {
|
|
SetInvalidSites(j, ARC, k, ARC, eps);
|
|
restart = false;
|
|
return false; /* duplicate arcs ! */
|
|
}
|
|
}
|
|
*cntr = GetPntCoords(m);
|
|
*r2 = 0.0;
|
|
*site = m;
|
|
return true; /* common end point */
|
|
}
|
|
ik_joint = true;
|
|
}
|
|
else if (IsArcStartPnt(j, m) || IsArcEndPnt(j, m)) {
|
|
jk_joint = true;
|
|
}
|
|
m = Get2ndVtx(k, ARC);
|
|
if (IsArcStartPnt(i, m) || IsArcEndPnt(i, m)) {
|
|
if (ik_joint) {
|
|
if (le(PntPntDist(GetArcCenter(i),GetArcCenter(k)), eps)) {
|
|
SetInvalidSites(i, ARC, k, ARC, eps);
|
|
restart = false;
|
|
return false; /* duplicate arcs ! */
|
|
}
|
|
}
|
|
if (IsArcStartPnt(j, m) || IsArcEndPnt(j, m)) {
|
|
if (jk_joint) {
|
|
if (le(PntPntDist(GetArcCenter(j),GetArcCenter(k)), eps)) {
|
|
SetInvalidSites(j, ARC, k, ARC, eps);
|
|
restart = false;
|
|
return false; /* duplicate arcs ! */
|
|
}
|
|
}
|
|
*cntr = GetPntCoords(m);
|
|
*r2 = 0.0;
|
|
*site = m;
|
|
return true; /* common end point */
|
|
}
|
|
}
|
|
else if (IsArcStartPnt(j, m) || IsArcEndPnt(j, m)) {
|
|
if (jk_joint) {
|
|
if (le(PntPntDist(GetArcCenter(j),GetArcCenter(k)), eps)) {
|
|
SetInvalidSites(j, ARC, k, ARC, eps);
|
|
restart = false;
|
|
return false; /* duplicate arcs ! */
|
|
}
|
|
}
|
|
}
|
|
m = Get1stVtx(i, ARC);
|
|
if (IsArcStartPnt(j, m) || IsArcEndPnt(j, m)) {
|
|
m = Get2ndVtx(i, ARC);
|
|
if (IsArcStartPnt(j, m) || IsArcEndPnt(j, m)) {
|
|
if (le(PntPntDist(GetArcCenter(i),GetArcCenter(j)), eps)) {
|
|
SetInvalidSites(i, ARC, j, ARC, eps);
|
|
restart = false;
|
|
return false; /* duplicate arcs ! */
|
|
}
|
|
}
|
|
}
|
|
|
|
eps = ZERO;
|
|
|
|
while (eps <= ZERO_MAX) {
|
|
no_check = false;
|
|
ij_joint = false;
|
|
jk_joint = false;
|
|
ik_joint = false;
|
|
is_special = false;
|
|
num_sol = 0;
|
|
|
|
/* */
|
|
/* check whether any pair of the arcs has (roughly) a common endpoint */
|
|
/* */
|
|
spi = GetArcStartCoord(i);
|
|
epi = GetArcEndCoord(i);
|
|
spj = GetArcStartCoord(j);
|
|
epj = GetArcEndCoord(j);
|
|
spk = GetArcStartCoord(k);
|
|
epk = GetArcEndCoord(k);
|
|
if ((PntPntDist(spi,spj) <= eps) || (PntPntDist(spi,epj) <= eps) ||
|
|
(PntPntDist(epi,spj) <= eps) || (PntPntDist(epi,epj) <= eps))
|
|
ij_joint = true;
|
|
if ((PntPntDist(spj,spk) <= eps) || (PntPntDist(spj,epk) <= eps) ||
|
|
(PntPntDist(epj,spk) <= eps) || (PntPntDist(epj,epk) <= eps))
|
|
jk_joint = true;
|
|
if ((PntPntDist(spi,spk) <= eps) || (PntPntDist(spi,epk) <= eps) ||
|
|
(PntPntDist(epi,spk) <= eps) || (PntPntDist(epi,epk) <= eps))
|
|
ik_joint = true;
|
|
|
|
/* */
|
|
/* if common endpoints exist then we rearrange the indices of the */
|
|
/* arcs such that the first and the second arc have a common endpoint */
|
|
/* and, possibly, also the second and the third arc have a common */
|
|
/* endpoint */
|
|
/* */
|
|
if (ij_joint) {
|
|
if (jk_joint) { /* keep original i-j-k order */
|
|
}
|
|
else if (ik_joint) { /* put into the order j-i-k */
|
|
VroniSwap(i, j, tmpi);
|
|
VroniSwap(spi, spj, tmp);
|
|
VroniSwap(epi, epj, tmp);
|
|
jk_joint = true;
|
|
ik_joint = false;
|
|
}
|
|
else { /* keep original i-j-k order */
|
|
}
|
|
}
|
|
else if (ik_joint) {
|
|
if (jk_joint) { /* put into the order i-k-j */
|
|
VroniSwap(j, k, tmpi);
|
|
VroniSwap(spj, spk, tmp);
|
|
VroniSwap(epj, epk, tmp);
|
|
ij_joint = true;
|
|
ik_joint = false;
|
|
}
|
|
else { /* put into the order i-k-j */
|
|
VroniSwap(j, k, tmpi);
|
|
VroniSwap(spj, spk, tmp);
|
|
VroniSwap(epj, epk, tmp);
|
|
ij_joint = true;
|
|
ik_joint = false;
|
|
}
|
|
}
|
|
else if (jk_joint) { /* put into the order k-j-i */
|
|
VroniSwap(i, k, tmpi);
|
|
VroniSwap(spi, spk, tmp);
|
|
VroniSwap(epi, epk, tmp);
|
|
ij_joint = true;
|
|
jk_joint = false;
|
|
}
|
|
else { /* keep original i-j-k order */
|
|
}
|
|
|
|
c1 = GetArcCenter(i);
|
|
c2 = GetArcCenter(j);
|
|
c3 = GetArcCenter(k);
|
|
rr1 = GetArcRadius(i);
|
|
rr2 = GetArcRadius(j);
|
|
rr3 = GetArcRadius(k);
|
|
|
|
d_c1c2 = PntPntDist(c1,c2);
|
|
d_c2c3 = PntPntDist(c2,c3);
|
|
d_c1c3 = PntPntDist(c1,c3);
|
|
|
|
if (ij_joint) {
|
|
if (Abs(rr1+rr2 - d_c1c2) <= eps) {
|
|
ij_counter = ((VecDet(c1,c2,spi) + VecDet(c1,c2,epi))*
|
|
(VecDet(c1,c2,spj) + VecDet(c1,c2,epj)) <= eps);
|
|
ij_tangent = false;
|
|
}
|
|
else {
|
|
ij_counter = false;
|
|
ij_tangent = ((Abs(Abs(rr1-rr2) - d_c1c2) <= eps) &&
|
|
((VecDet(c1,c2,spi) + VecDet(c1,c2,epi))*
|
|
(VecDet(c1,c2,spj) + VecDet(c1,c2,epj)) <= eps));
|
|
}
|
|
if (jk_joint) {
|
|
if (Abs(rr2+rr3 - d_c2c3) <= eps) {
|
|
jk_counter = ((VecDet(c2,c3,spj) + VecDet(c2,c3,epj))*
|
|
(VecDet(c2,c3,spk) + VecDet(c2,c3,epk)) <= eps);
|
|
jk_tangent = false;
|
|
}
|
|
else {
|
|
jk_counter = false;
|
|
jk_tangent = ((Abs(Abs(rr2-rr3) - d_c2c3) <= eps) &&
|
|
((VecDet(c2,c3,spj) + VecDet(c2,c3,epj))*
|
|
(VecDet(c2,c3,spk) + VecDet(c2,c3,epk)) <= eps));
|
|
}
|
|
}
|
|
else {
|
|
jk_counter = jk_tangent = false;
|
|
}
|
|
if (ik_joint) {
|
|
if (Abs(rr1+rr3 - d_c1c3) <= eps) {
|
|
ik_counter = ((VecDet(c1,c3,spj) + VecDet(c1,c3,epj))*
|
|
(VecDet(c1,c3,spk) + VecDet(c1,c3,epk)) <= eps);
|
|
ik_tangent = false;
|
|
}
|
|
else {
|
|
ik_counter = false;
|
|
ik_tangent = ((Abs(Abs(rr1-rr3) - d_c1c3) <= eps) &&
|
|
((VecDet(c1,c3,spj) + VecDet(c1,c3,epj))*
|
|
(VecDet(c1,c3,spk) + VecDet(c1,c3,epk)) <= eps));
|
|
}
|
|
}
|
|
else {
|
|
ik_counter = ik_tangent = false;
|
|
}
|
|
}
|
|
else {
|
|
ij_counter = ij_tangent = jk_counter = jk_tangent = false;
|
|
ik_counter = ik_tangent = false;
|
|
}
|
|
|
|
if (!(ij_counter || ij_tangent)) {
|
|
if (ik_tangent || ik_counter) {
|
|
VroniSwap(ij_counter, ik_counter, tmpi);
|
|
VroniSwap(ij_tangent, ik_tangent, tmpi);
|
|
VroniSwap(j, k, tmpi);
|
|
VroniSwap(spj, spk, tmp);
|
|
VroniSwap(epj, epk, tmp);
|
|
VroniSwap(c2, c3, tmp);
|
|
VroniSwap(rr2, rr3, tmpr);
|
|
VroniSwap(d_c1c2, d_c1c3, tmpr);
|
|
}
|
|
else if (jk_tangent || jk_counter) {
|
|
VroniSwap(ij_counter, jk_counter, tmpi);
|
|
VroniSwap(ij_tangent, jk_tangent, tmpi);
|
|
VroniSwap(i, k, tmpi);
|
|
VroniSwap(spi, spk, tmp);
|
|
VroniSwap(epi, epk, tmp);
|
|
VroniSwap(c1, c3, tmp);
|
|
VroniSwap(rr1, rr3, tmpr);
|
|
VroniSwap(d_c1c2, d_c2c3, tmpr);
|
|
}
|
|
}
|
|
else if (!(jk_counter || jk_tangent)) {
|
|
if (ik_tangent || ik_counter) {
|
|
VroniSwap(ij_counter, ik_counter, tmpi);
|
|
VroniSwap(ij_tangent, ik_tangent, tmpi);
|
|
VroniSwap(j, k, tmpi);
|
|
VroniSwap(spj, spk, tmp);
|
|
VroniSwap(epj, epk, tmp);
|
|
VroniSwap(c2, c3, tmp);
|
|
VroniSwap(rr2, rr3, tmpr);
|
|
VroniSwap(d_c1c2, d_c1c3, tmpr);
|
|
|
|
VroniSwap(ij_counter, jk_counter, tmpi);
|
|
VroniSwap(ij_tangent, jk_tangent, tmpi);
|
|
VroniSwap(i, j, tmpi);
|
|
VroniSwap(spi, spj, tmp);
|
|
VroniSwap(epi, epj, tmp);
|
|
VroniSwap(c1, c2, tmp);
|
|
VroniSwap(rr1, rr2, tmpr);
|
|
VroniSwap(d_c2c3, d_c1c3, tmpr);
|
|
}
|
|
}
|
|
|
|
if (jk_counter || jk_tangent) {
|
|
if (ij_tangent && jk_tangent) {
|
|
/* */
|
|
/* two tangential joints? then the three arcs should lie */
|
|
/* roughly on the same circle! */
|
|
/* */
|
|
if ((d_c1c2 <= eps) && (d_c2c3 <= eps) && (d_c1c3 <= eps)) {
|
|
num_sol = 1;
|
|
centers[0].x = (c1.x + c2.x + c3.x) / 3.0;
|
|
centers[0].y = (c1.y + c2.y + c3.y) / 3.0;
|
|
radii[0] = (rr1 + rr2 + rr3) / 3.0;
|
|
no_check = true;
|
|
is_special = true;
|
|
}
|
|
}
|
|
else if (ij_tangent && jk_counter) {
|
|
/* */
|
|
/* one meeting is tangential, the other is counter-tangential */
|
|
/* */
|
|
if (d_c1c2 <= eps) {
|
|
num_sol = 1;
|
|
centers[0] = MidPoint(c1,c2);
|
|
radii[0] = (rr1 + rr2) / 2.0;
|
|
no_check = true;
|
|
is_special = true;
|
|
}
|
|
}
|
|
else if (ij_counter && jk_tangent) {
|
|
/* */
|
|
/* one meeting is tangential, the other is counter-tangential */
|
|
/* */
|
|
if (d_c2c3 <= eps) {
|
|
num_sol = 1;
|
|
centers[0] = MidPoint(c2,c3);
|
|
radii[0] = (rr2 + rr3) / 2.0;
|
|
no_check = true;
|
|
is_special = true;
|
|
}
|
|
}
|
|
else if (ij_counter && jk_counter) {
|
|
/* */
|
|
/* both meetings are counter-tangential */
|
|
/* */
|
|
num_sol = 1;
|
|
centers[0] = c2;
|
|
radii[0] = rr2;
|
|
no_check = true;
|
|
is_special = true;
|
|
}
|
|
}
|
|
|
|
if (!is_special) {
|
|
if (ij_counter) {
|
|
/* */
|
|
/* two counter-tangential arcs with common endpoint and on */
|
|
/* different sides of the center-line */
|
|
/* */
|
|
//printf("\ttwo counter-tangential circles (%d-%d-%d)\n", i, j ,k);
|
|
if ((PntPntDist(spi,spj) <= eps) || (PntPntDist(spi,epj) <= eps))
|
|
ep = spi;
|
|
else
|
|
ep = epi;
|
|
v = VecSub(ep, c1);
|
|
num_sol = IntersectRayCircle(ep, v, c3, rr3, centers, radii, eps);
|
|
is_special = true;
|
|
}
|
|
else if (ij_tangent) {
|
|
/* */
|
|
/* two tangential arcs with common endpoint */
|
|
/* */
|
|
// printf("\ttwo tangential circles (%d-%d-%d)\n", i, j ,k);
|
|
|
|
if ((i == i_in) || (j == i_in)) {
|
|
n1 = GetStartNode(e);
|
|
if (!IsNodeDeleted(n1)) n1 = GetEndNode(e);
|
|
if (IsNodeDeleted(n1)) {
|
|
GetNodeData(n1, &tmp, &rad);
|
|
num_sol = 1;
|
|
centers[0] = tmp;
|
|
radii[0] = rad;
|
|
no_check = true;
|
|
}
|
|
}
|
|
|
|
if (!no_check) {
|
|
if ((PntPntDist(spi,spj) <= eps) || (PntPntDist(spi,epj) <= eps))
|
|
ep = spi;
|
|
else
|
|
ep = epi;
|
|
v = VecSub(ep, c1);
|
|
num_sol = IntersectRayCircle(ep, v, c3, rr3, centers, radii,
|
|
eps);
|
|
|
|
}
|
|
is_special = true;
|
|
}
|
|
}
|
|
|
|
if (!is_special) {
|
|
ij_tangent = (!ij_joint) && ((d_c1c2 <= eps) &&
|
|
(Abs(rr1-rr2) <= eps));
|
|
ik_tangent = (!ik_joint) && ((d_c1c3 <= eps) &&
|
|
(Abs(rr1-rr3) <= eps));
|
|
jk_tangent = (!jk_joint) && ((d_c2c3 <= eps) &&
|
|
(Abs(rr2-rr3) <= eps));
|
|
}
|
|
if (!is_special && (ij_tangent || jk_tangent || ik_tangent)) {
|
|
if ((ij_tangent && ik_tangent) || (ij_tangent && jk_tangent) ||
|
|
(ik_tangent && jk_tangent)) {
|
|
/* */
|
|
/* three arcs on a common circle without common endpoint */
|
|
/* */
|
|
//printf("\tthree common circles\n");
|
|
num_sol = 1;
|
|
centers[0].x = (c1.x + c2.x + c3.x) / 3.0;
|
|
centers[0].y = (c1.y + c2.y + c3.y) / 3.0;
|
|
radii[0] = (rr1 + rr2 + rr3) / 3.0;
|
|
no_check = true;
|
|
is_special = true;
|
|
}
|
|
else {
|
|
/* */
|
|
/* two arcs on the same circle, but without common endpoint */
|
|
/* */
|
|
if (ik_tangent) {
|
|
VroniSwap(j, k, tmpi);
|
|
VroniSwap(c2, c3, tmp);
|
|
VroniSwap(rr2, rr3, tmpr);
|
|
}
|
|
else if (jk_tangent) {
|
|
VroniSwap(i, k, tmpi);
|
|
VroniSwap(c1, c3, tmp);
|
|
VroniSwap(rr1, rr3, tmpr);
|
|
}
|
|
//printf("\tspecial case: cocircular disjoint circles: %d-%d-%d\n", i, j ,k);
|
|
num_sol = 1;
|
|
centers[0] = MidPoint(c1,c2);
|
|
radii[0] = (rr1 + rr2) / 2.0;
|
|
no_check = true;
|
|
is_special = true;
|
|
}
|
|
}
|
|
|
|
if (!is_special) {
|
|
/* */
|
|
/* if two arcs are counter-tangential but do not share an endpoint: */
|
|
/* check whether one endpoint lies on line through centers */
|
|
/* */
|
|
if ((!ij_joint) && (Abs(rr1+rr2 - d_c1c2) <= eps)) {
|
|
if (eq(VecDet(c1,c2,spi), eps) ||
|
|
eq(VecDet(c1,c2,epi), eps) ||
|
|
eq(VecDet(c1,c2,spj), eps) ||
|
|
eq(VecDet(c1,c2,epj), eps)) {
|
|
is_special = true;
|
|
centers[0] = c1;
|
|
centers[1] = c2;
|
|
radii[0] = rr1;
|
|
radii[1] = rr2;
|
|
num_sol = 2;
|
|
}
|
|
}
|
|
if ((!jk_joint) && (Abs(rr2+rr3 - d_c2c3) <= eps)) {
|
|
if (eq(VecDet(c2,c3,spj), eps) ||
|
|
eq(VecDet(c2,c3,epj), eps) ||
|
|
eq(VecDet(c2,c3,spk), eps) ||
|
|
eq(VecDet(c2,c3,epk), eps)) {
|
|
is_special = true;
|
|
centers[0] = c2;
|
|
centers[1] = c3;
|
|
radii[0] = rr2;
|
|
radii[1] = rr3;
|
|
num_sol = 2;
|
|
}
|
|
}
|
|
if ((!ik_joint) && (Abs(rr1+rr3 - d_c1c3) <= eps)) {
|
|
if (eq(VecDet(c1,c3,spi), eps) ||
|
|
eq(VecDet(c1,c3,epi), eps) ||
|
|
eq(VecDet(c1,c3,spk), eps) ||
|
|
eq(VecDet(c1,c3,epk), eps)) {
|
|
is_special = true;
|
|
centers[0] = c1;
|
|
centers[1] = c3;
|
|
radii[0] = rr1;
|
|
radii[1] = rr3;
|
|
num_sol = 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!is_special) {
|
|
/* */
|
|
/* general case */
|
|
/* */
|
|
#ifdef TRACE
|
|
if ((i == 4416) && (j == 4617) && (k == 4713)) {
|
|
printf("\tordinary\n");
|
|
printf("rr1 = %20.16f\n", rr1);
|
|
printf("rr2 = %20.16f\n", rr2);
|
|
printf("rr3 = %20.16f\n", rr3);
|
|
}
|
|
#endif
|
|
//Determining good sequence of arcs to get good results
|
|
if ( rr1 < rr2 ) {
|
|
coord tmpc;
|
|
double tmpd;
|
|
int tmpi;
|
|
VroniSwap(c1,c2, tmpc);
|
|
VroniSwap(rr1,rr2, tmpd);
|
|
VroniSwap(i,j, tmpi);
|
|
}
|
|
if ( rr1 < rr3 ) {
|
|
coord tmpc;
|
|
double tmpd;
|
|
int tmpi;
|
|
VroniSwap(c1,c3, tmpc);
|
|
VroniSwap(rr1,rr3, tmpd);
|
|
VroniSwap(i,k, tmpi);
|
|
}
|
|
if ( rr2 < rr3 ) {
|
|
coord tmpc;
|
|
double tmpd;
|
|
int tmpi;
|
|
VroniSwap(c2,c3, tmpc);
|
|
VroniSwap(rr2,rr3, tmpd);
|
|
VroniSwap(j,k, tmpi);
|
|
}
|
|
|
|
num_sol = CircCircCircCenters(c1, c2, c3, rr1, rr2, rr3, centers,
|
|
radii, eps);
|
|
#ifdef TRACE
|
|
printf("in the general case! num_sol = %d\n", num_sol);
|
|
printf("i_in = %d, j_in = %d, k_in = %d\n", i_in, j_in, k_in);
|
|
#endif
|
|
}
|
|
|
|
if ((num_sol > 0) && no_check)
|
|
best_sol = 0;
|
|
else
|
|
/* */
|
|
/* classify all solutions and pick the best solution */
|
|
/* */
|
|
best_sol = ClassifySolutions(i_in, j_in, k_in, e, ARC, ARC, ARC,
|
|
false, true, true, centers, radii,
|
|
&num_sol, eps, problematic);
|
|
assert((0 <= best_sol) && (best_sol < num_sol));
|
|
if (!*problematic) {
|
|
*cntr = centers[best_sol];
|
|
*r2 = radii[best_sol];
|
|
return true;
|
|
}
|
|
else {
|
|
eps *= 10.0;
|
|
}
|
|
}
|
|
|
|
if (eq(GetArcRadius(i), ZERO_MAX)) {
|
|
/* */
|
|
/* this is an arc with a very small radius; we replace it */
|
|
/* by a seg */
|
|
/* */
|
|
VD_Dbg_Warning("ArcArcArcCntr() - arc with small radius!");
|
|
ReplaceArc(i);
|
|
restart = true;
|
|
return false;
|
|
}
|
|
else if (eq(GetArcRadius(j), ZERO_MAX)) {
|
|
/* */
|
|
/* this is an arc with a very small radius; we replace it */
|
|
/* by a seg */
|
|
/* */
|
|
VD_Dbg_Warning("ArcArcArcCntr() - arc with small radius!");
|
|
ReplaceArc(j);
|
|
restart = true;
|
|
return false;
|
|
}
|
|
else if (eq(GetArcRadius(k), ZERO_MAX)) {
|
|
/* */
|
|
/* this is an arc with a very small radius; we replace it */
|
|
/* by a seg */
|
|
/* */
|
|
VD_Dbg_Warning("ArcArcArcCntr() - arc with small radius!");
|
|
ReplaceArc(k);
|
|
restart = true;
|
|
return false;
|
|
}
|
|
else if (eq(PntPntDist(GetArcStartCoord(i), GetArcEndCoord(i)), ZERO_MAX)) {
|
|
/* */
|
|
/* this is an arc with a very short cord; we replace it by a seg */
|
|
/* */
|
|
VD_Dbg_Warning("ArcArcArcCntr() - arc with short cord!");
|
|
ReplaceArc(i);
|
|
restart = true;
|
|
return false;
|
|
}
|
|
else if (eq(PntPntDist(GetArcStartCoord(j), GetArcEndCoord(j)), ZERO_MAX)) {
|
|
/* */
|
|
/* this is an arc with a very short cord; we replace it by a seg */
|
|
/* */
|
|
VD_Dbg_Warning("ArcArcArcCntr() - arc with short cord!");
|
|
ReplaceArc(j);
|
|
restart = true;
|
|
return false;
|
|
}
|
|
else if (eq(PntPntDist(GetArcStartCoord(k), GetArcEndCoord(k)), ZERO_MAX)) {
|
|
/* */
|
|
/* this is an arc with a very short cord; we replace it by a seg */
|
|
/* */
|
|
VD_Dbg_Warning("ArcArcArcCntr() - arc with short cord!");
|
|
ReplaceArc(k);
|
|
restart = true;
|
|
return false;
|
|
}
|
|
else if (CheckIntersectionsLocally(i, ARC, j, ARC, k, ARC)) {
|
|
restart = true;
|
|
return false;
|
|
}
|
|
|
|
#ifdef VRONI_DBG_WARN
|
|
spi = GetArcStartCoord(i);
|
|
spj = GetArcStartCoord(j);
|
|
spk = GetArcStartCoord(k);
|
|
epj = GetArcEndCoord(j);
|
|
epi = GetArcEndCoord(i);
|
|
epk = GetArcEndCoord(k);
|
|
c1 = GetArcCenter(i);
|
|
c2 = GetArcCenter(j);
|
|
c3 = GetArcCenter(k);
|
|
printf("\nCenter not computed for arc-arc-arc:\n");
|
|
printf("%20.16f %20.16f %20.16f %20.16f %20.16f %20.16f\n",
|
|
spi.x, spi.y, epi.x, epi.y, c1.x, c1.y);
|
|
printf("%20.16f %20.16f %20.16f %20.16f %20.16f %20.16f\n",
|
|
spj.x, spj.y, epj.x, epj.y, c2.x, c2.y);
|
|
printf("%20.16f %20.16f %20.16f %20.16f %20.16f %20.16f\n",
|
|
spk.x, spk.y, epk.x, epk.y, c3.x, c3.y);
|
|
#endif
|
|
|
|
*cntr = centers[best_sol];
|
|
*r2 = radii[best_sol];
|
|
restart = false;
|
|
|
|
return false;
|
|
}
|
|
|
|
|