Files
vroni/arc_arc_arc.cc
T
SaraP f3e15b8c8d vroni 7.6 :
- aggiunti file della libreria e progetto visual studio.
2023-09-06 15:44:02 +02:00

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 */
Swap(i, j, tmpi);
Swap(spi, spj, tmp);
Swap(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 */
Swap(j, k, tmpi);
Swap(spj, spk, tmp);
Swap(epj, epk, tmp);
ij_joint = true;
ik_joint = false;
}
else { /* put into the order i-k-j */
Swap(j, k, tmpi);
Swap(spj, spk, tmp);
Swap(epj, epk, tmp);
ij_joint = true;
ik_joint = false;
}
}
else if (jk_joint) { /* put into the order k-j-i */
Swap(i, k, tmpi);
Swap(spi, spk, tmp);
Swap(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) {
Swap(ij_counter, ik_counter, tmpi);
Swap(ij_tangent, ik_tangent, tmpi);
Swap(j, k, tmpi);
Swap(spj, spk, tmp);
Swap(epj, epk, tmp);
Swap(c2, c3, tmp);
Swap(rr2, rr3, tmpr);
Swap(d_c1c2, d_c1c3, tmpr);
}
else if (jk_tangent || jk_counter) {
Swap(ij_counter, jk_counter, tmpi);
Swap(ij_tangent, jk_tangent, tmpi);
Swap(i, k, tmpi);
Swap(spi, spk, tmp);
Swap(epi, epk, tmp);
Swap(c1, c3, tmp);
Swap(rr1, rr3, tmpr);
Swap(d_c1c2, d_c2c3, tmpr);
}
}
else if (!(jk_counter || jk_tangent)) {
if (ik_tangent || ik_counter) {
Swap(ij_counter, ik_counter, tmpi);
Swap(ij_tangent, ik_tangent, tmpi);
Swap(j, k, tmpi);
Swap(spj, spk, tmp);
Swap(epj, epk, tmp);
Swap(c2, c3, tmp);
Swap(rr2, rr3, tmpr);
Swap(d_c1c2, d_c1c3, tmpr);
Swap(ij_counter, jk_counter, tmpi);
Swap(ij_tangent, jk_tangent, tmpi);
Swap(i, j, tmpi);
Swap(spi, spj, tmp);
Swap(epi, epj, tmp);
Swap(c1, c2, tmp);
Swap(rr1, rr2, tmpr);
Swap(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) {
Swap(j, k, tmpi);
Swap(c2, c3, tmp);
Swap(rr2, rr3, tmpr);
}
else if (jk_tangent) {
Swap(i, k, tmpi);
Swap(c1, c3, tmp);
Swap(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;
Swap(c1,c2, tmpc);
Swap(rr1,rr2, tmpd);
Swap(i,j, tmpi);
}
if ( rr1 < rr3 ) {
coord tmpc;
double tmpd;
int tmpi;
Swap(c1,c3, tmpc);
Swap(rr1,rr3, tmpd);
Swap(i,k, tmpi);
}
if ( rr2 < rr3 ) {
coord tmpc;
double tmpd;
int tmpi;
Swap(c2,c3, tmpc);
Swap(rr2,rr3, tmpd);
Swap(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;
}