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

330 lines
14 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 "numerics.h"
#include "defs.h"
#include "roots.h"
/* */
/* Calculate the Voronoi center of arc, seg and pnt */
/* */
vr_bool vroniObject::ArcSegPntCntr(int i, int j, int k, int e,
coord* cntr, double *r2,
vr_bool *problematic, int* site)
{
coord c1, c2;
double rr1, rr2;
double s1a, s1b, s1c;
coord centers[VRONI_MAXSOL];
double radii[VRONI_MAXSOL];
int num_sol = 0, best_sol = NIL, old_num_sol = 0;;
double d_c1c2;
double eps = ZERO;
vr_bool counter_tangential, is_endpoint, is_special, is_tangent;
vr_bool is_pnt_on_line, is_pnt_on_circle;
coord spi, epi;
coord ep, sp, u, v, w;
#ifdef VRONI_DBG_WARN
coord spj, epj;
#endif
/* */
/* Check whether the three sites are all in lists */
/* */
assert(InArcsList(i));
assert(InSegsList(j));
assert(InPntsList(k));
*problematic = false;
if ((IsArcStartPnt(i,k) || IsArcEndPnt(i,k)) &&
(IsSegStartPnt(j,k) || IsSegEndPnt(j,k))) {
/* */
/* pnt k is a common end-point of i and j. */
/* */
//printf("\n\nPoint splits arc-seg\n\n");
*cntr = GetPntCoords(k);
*r2 = 0.0;
*site = k;
return true;
}
c1 = GetArcCenter(i);
c2 = GetPntCoords(k);
rr1 = GetArcRadius(i);
rr2 = 0;
GetSegEqnData(j, &s1a, &s1b, &s1c);
s1c*=-1;
spi = GetArcStartCoord(i);
epi = GetArcEndCoord(i);
#ifdef TRACE
printf("arc%d-seg%d-pnt%d:\n", i, j, k);
printf("arc: (%20.16f %20.16f) %20.16f\n", c1.x, c1.y, rr1);
printf("pnt: (%20.16f %20.16f %20.16f)\n", s1a, s1b, s1c);
#endif
d_c1c2 = PntPntDist(c1, c2);
if (IsArcStartPnt(i,k) || IsArcEndPnt(i,k)) {
if ( Abs(PntLineDist(s1a, s1b, -s1c, c1)) < rr1 )
v = VecSub(c1, c2);
else
v = VecSub(c2, c1);
is_endpoint = true;
old_num_sol = IntersectRaySegment(c2, v, s1a, s1b, s1c, centers, radii,
ZERO);
}
else if (IsSegStartPnt(j,k) || IsSegEndPnt(j,k)) {
u = VecSub(c1,c2);
v = MakeVec(s1a, s1b);
/* */
/* if arc is between c1 and c2 and v points away from c1, or */
/* if arc is not between c1 and c2 and v points to c1, */
/* then invert v */
/* */
if ((d_c1c2 > rr1) && (v.x*u.x + v.y*u.y < 0)) v = VecMult(-1.0, v);
if ((d_c1c2 < rr1) && (v.x*u.x + v.y*u.y > 0)) v = VecMult(-1.0, v);
is_endpoint = true;
old_num_sol = IntersectRayCircle(c2, v, c1, rr1, centers, radii, ZERO);
}
else {
is_endpoint = false;
}
while (eps <= ZERO_MAX) {
is_special = false;
num_sol = old_num_sol;
if (!is_endpoint) {
if (DoArcPntIntersect(i, c2, eps)) {
VD_Dbg_Warning("ArcSegPntCntr() - point lies in interior of arc!");
SetInvalidSites(i, ARC, k, PNT, eps);
restart = false;
return false;
}
is_pnt_on_line = (Abs(PntLineDist(s1a, s1b, -s1c, c2)) <= eps);
is_pnt_on_circle = (Abs(d_c1c2-rr1) <= eps);
is_tangent = (Abs(Abs(c1.x*s1a+c1.y*s1b-s1c)-rr1) <= eps);
if (is_pnt_on_line && is_pnt_on_circle && is_tangent) {
/* */
/* circle and line are tangent in the pnt */
/* */
if (IsPntInArcCone(i, c2)) {
centers[0]= c2;
radii[0] = 0.0;
}
else {
centers[0]= c1;
radii[0] = rr1;
}
num_sol = 1;
is_special = true;
}
else if (is_pnt_on_circle && IsPntInArcCone(i,c2) && (rr1 > eps)) {
/* */
/* pnt is on the circle */
/* */
if (Abs(PntLineDist(s1a, s1b, -s1c, c1)) < rr1)
v = VecSub(c1, c2);
else
v = VecSub(c2, c1);
num_sol = IntersectRaySegment(c2, v, s1a, s1b, s1c, centers,
radii, eps);
is_special = true;
}
else if (is_pnt_on_line) {
/* */
/* pnt is on the line */
/* */
//printf("asp: special case: point is on line\n");
u = VecSub(c1,c2);
v = MakeVec(s1a, s1b);
/* */
/* if arc is between c1 and c2 and v points away from c1, */
/* or */
/* if arc is not between c1 and c2 and v points to c1, */
/* then invert v */
/* */
if (((d_c1c2 > rr1) && (v.x*u.x + v.y*u.y) < 0))
v = VecMult(-1.0, v);
if (((d_c1c2 < rr1) && (v.x*u.x + v.y*u.y) > 0))
v = VecMult(-1.0, v);
num_sol = IntersectRayCircle(c2, v, c1, rr1, centers, radii, eps);
is_special = true;
}
else if (is_tangent) {
/* */
/* line is tangent to circle */
/* */
counter_tangential = true;
if (PntPntDist(GetArcStartCoord(i),GetSegStartCoord(j)) <= eps) {
ep = GetSegStartCoord(j);
sp = GetSegEndCoord(j);
v = VecSub(sp, ep);
w = VecSub(epi, ep);
counter_tangential = (VecDotProd(v, w) < 0.0) ? false : true;
}
else if (PntPntDist(GetArcEndCoord(i),GetSegStartCoord(j)) <= eps) {
ep = GetSegStartCoord(j);
sp = GetSegEndCoord(j);
v = VecSub(sp, ep);
w = VecSub(spi, ep);
counter_tangential = (VecDotProd(v, w) < 0.0) ? false : true;
}
else if (PntPntDist(GetArcStartCoord(i),GetSegEndCoord(j)) <= eps) {
ep = GetSegEndCoord(j);
sp = GetSegStartCoord(j);
v = VecSub(sp, ep);
w = VecSub(epi, ep);
counter_tangential = (VecDotProd(v, w) < 0.0) ? false : true;
}
else if (PntPntDist(GetArcEndCoord(i),GetSegEndCoord(j)) <= eps) {
ep = GetSegEndCoord(j);
sp = GetSegStartCoord(j);
v = VecSub(sp, ep);
w = VecSub(spi, ep);
counter_tangential = (VecDotProd(v, w) < 0.0) ? false : true;
}
if (!counter_tangential) {
if ((s1a*c2.x+s1b*c2.y-s1c) > 0.0) v = MakeVec(s1a, s1b);
else v = MakeVec(-s1a, -s1b);
num_sol = IntersectRayCircle(ep, v, c2, 0.0, centers, radii,
eps);
is_special = true;
}
}
if (!is_special) {
/* */
/* and finally the general case... */
/* */
//printf("ordinary\n");
num_sol = CircCircSegCenters(c1, c2, rr1, rr2, s1a, s1b, s1c,
centers, radii, eps);
}
}
/* */
/* classify all solutions and pick the best solution */
/* */
best_sol = ClassifySolutions(i, j, k, e, ARC, SEG, PNT,
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(rr1, ZERO_MAX)) {
/* */
/* this is an arc with a very small radius; we replace it by */
/* by a seg */
/* */
VD_Dbg_Warning("ArcSegPntCntr() - arc with small radius!");
ReplaceArc(i);
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("ArcSegPntCntr() - arc with short cord!");
ReplaceArc(i);
restart = true;
return false;
}
else if (eq(GetSegLgth(j), ZERO_MAX)) {
/* */
/* this is a seg with a very small length; we replace it */
/* */
VD_Dbg_Warning("ArcSegPntCntr() - seg with small length!");
ReplaceSeg(j);
restart = true;
return false;
}
else if (CheckIntersectionsLocally(i, ARC, j, SEG, k, PNT)) {
restart = true;
return false;
}
#ifdef VRONI_DBG_WARN
spi = GetArcStartCoord(i);
epi = GetArcEndCoord(i);
c1 = GetArcCenter(i);
printf("\nCenter not computed for arc-seg-pnt:\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);
epj = GetSegStartCoord(j);
spj = GetSegEndCoord(j);
printf("%20.16f %20.16f %20.16f %20.16f\n",
spj.x, spj.y, epj.x, epj.y);
c2 = GetPntCoords(k);
printf("%20.16f %20.16f\n", c2.x, c2.y);
#endif
*cntr = centers[best_sol];
*r2 = radii[best_sol];
restart = false;
return false;
}