PostGIS  3.2.2dev-r@@SVN_REVISION@@

◆ lw_dist2d_arc_arc()

int lw_dist2d_arc_arc ( const POINT2D A1,
const POINT2D A2,
const POINT2D A3,
const POINT2D B1,
const POINT2D B2,
const POINT2D B3,
DISTPTS dl 
)

Definition at line 1676 of file measures.c.

1680 {
1681  POINT2D pts_A[16]; /* Points on A that might be the nearest */
1682  POINT2D pts_B[16]; /* Points on B that might be the nearest */
1683  uint32_t ai = 0, bi = 0; /* Number of points in pts_A and pts_B */
1684  POINT2D center_A, center_B; /* Center points of arcs A and B */
1685  double radius_A, radius_B, d; /* Radii of arcs A and B */
1686  int is_disjoint, is_overlapping, is_contained, is_same_center;
1687  POINT2D intersectionPts[2];
1688 
1689  if (dl->mode != DIST_MIN)
1690  lwerror("lw_dist2d_arc_arc only supports mindistance");
1691 
1692  /* What if one or both of our "arcs" is actually a point? */
1693  if (lw_arc_is_pt(B1, B2, B3) && lw_arc_is_pt(A1, A2, A3))
1694  return lw_dist2d_pt_pt(B1, A1, dl);
1695  else if (lw_arc_is_pt(B1, B2, B3))
1696  return lw_dist2d_pt_arc(B1, A1, A2, A3, dl);
1697  else if (lw_arc_is_pt(A1, A2, A3))
1698  return lw_dist2d_pt_arc(A1, B1, B2, B3, dl);
1699 
1700  /* Calculate centers and radii of circles. */
1701  radius_A = lw_arc_center(A1, A2, A3, &center_A);
1702  radius_B = lw_arc_center(B1, B2, B3, &center_B);
1703 
1704  /* Two co-linear arcs?!? That's two segments. */
1705  if (radius_A < 0 && radius_B < 0)
1706  return lw_dist2d_seg_seg(A1, A3, B1, B3, dl);
1707 
1708  /* A is co-linear, delegate to lw_dist_seg_arc here. */
1709  if (radius_A < 0)
1710  return lw_dist2d_seg_arc(A1, A3, B1, B2, B3, dl);
1711 
1712  /* B is co-linear, delegate to lw_dist_seg_arc here. */
1713  if (radius_B < 0)
1714  return lw_dist2d_seg_arc(B1, B3, A1, A2, A3, dl);
1715 
1716  /* Circle relationships */
1717  d = distance2d_pt_pt(&center_A, &center_B);
1718  is_disjoint = (d > (radius_A + radius_B));
1719  is_contained = (d < fabs(radius_A - radius_B));
1720  is_same_center = p2d_same(&center_A, &center_B);
1721  is_overlapping = ! (is_disjoint || is_contained || is_same_center);
1722 
1723  /*
1724  * Prime the array of potential closest points with the
1725  * arc end points, which frequently participate in closest
1726  * points.
1727  */
1728  pts_A[ai++] = *A1;
1729  pts_A[ai++] = *A3;
1730  pts_B[bi++] = *B1;
1731  pts_B[bi++] = *B3;
1732 
1733  /*
1734  * Overlapping circles might have a zero distance
1735  * case if the circle intersection points are inside both
1736  * arcs.
1737  */
1738  if (is_overlapping)
1739  {
1740  /*
1741  * Find the two points the circles intersect at.
1742  */
1743  uint32_t npoints = lw_dist2d_circle_circle_intersections(
1744  &center_A, radius_A,
1745  &center_B, radius_B,
1746  intersectionPts);
1747  for (uint32_t i = 0; i < npoints; i++)
1748  {
1749  /*
1750  * If an intersection point is contained in both
1751  * arcs, that is a location of zero distance, so
1752  * we are done calculating.
1753  */
1754  if (lw_pt_in_arc(&intersectionPts[i], A1, A2, A3) &&
1755  lw_pt_in_arc(&intersectionPts[i], B1, B2, B3))
1756  {
1757  lw_dist2d_distpts_set(dl, 0.0, &intersectionPts[i], &intersectionPts[i]);
1758  return LW_TRUE;
1759  }
1760  }
1761  }
1762 
1763  /*
1764  * Join the circle centers and find the places that
1765  * line intersects the circles. Where those places
1766  * are in the arcs, they are potential sites of the
1767  * closest points.
1768  */
1769  if (is_disjoint || is_contained || is_overlapping)
1770  {
1771  if (!is_same_center)
1772  {
1773  /* Add points on A that intersect line from center_A to center_B */
1775  A1, A2, A3,
1776  &center_A, radius_A, &center_B,
1777  pts_A, &ai);
1778 
1779  /* Add points on B that intersect line from center_B to center_A */
1781  B1, B2, B3,
1782  &center_B, radius_B, &center_A,
1783  pts_B, &bi);
1784  }
1785 
1786  /* Add points on A that intersect line to B1 */
1788  A1, A2, A3,
1789  &center_A, radius_A, B1,
1790  pts_A, &ai);
1791 
1792  /* Add points on A that intersect line to B3 */
1794  A1, A2, A3,
1795  &center_A, radius_A, B3,
1796  pts_A, &ai);
1797 
1798  /* Add points on B that intersect line to A1 */
1800  B1, B2, B3,
1801  &center_B, radius_B, A1,
1802  pts_B, &bi);
1803 
1804  /* Add points on B that intersect line to A3 */
1806  B1, B2, B3,
1807  &center_B, radius_B, A3,
1808  pts_B, &bi);
1809  }
1810 
1811  /*
1812  * Now just brute force check all pairs of participating
1813  * points, to find the pair that is closest together.
1814  */
1815  for (uint32_t i = 0; i < ai; i++)
1816  for (uint32_t j = 0; j < bi; j++)
1817  lw_dist2d_pt_pt(&pts_A[i], &pts_B[j], dl);
1818 
1819  return LW_TRUE;
1820 }
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:107
double lw_arc_center(const POINT2D *p1, const POINT2D *p2, const POINT2D *p3, POINT2D *result)
Determines the center of the circle defined by the three given points.
Definition: lwalgorithm.c:237
int lw_arc_is_pt(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
Returns true if arc A is actually a point (all vertices are the same) .
Definition: lwalgorithm.c:114
int lw_pt_in_arc(const POINT2D *P, const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
Returns true if P is on the same side of the plane partition defined by A1/A3 as A2 is.
Definition: lwalgorithm.c:84
int p2d_same(const POINT2D *p1, const POINT2D *p2)
Definition: lwalgorithm.c:50
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
static uint32_t lw_dist2d_circle_circle_intersections(const POINT2D *cA, double rA, const POINT2D *cB, double rB, POINT2D *I)
Calculates the intersection points of two overlapping circles.
Definition: measures.c:1626
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition: measures.c:2306
int lw_dist2d_pt_arc(const POINT2D *P, const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, DISTPTS *dl)
Definition: measures.c:1484
static void lw_dist2d_distpts_set(DISTPTS *dl, double distance, const POINT2D *p1, const POINT2D *p2)
Definition: measures.c:78
int lw_dist2d_seg_seg(const POINT2D *A, const POINT2D *B, const POINT2D *C, const POINT2D *D, DISTPTS *dl)
Finds the shortest distance between two segments.
Definition: measures.c:1829
int lw_dist2d_seg_arc(const POINT2D *A1, const POINT2D *A2, const POINT2D *B1, const POINT2D *B2, const POINT2D *B3, DISTPTS *dl)
Calculate the shortest distance between an arc and an edge.
Definition: measures.c:1340
int lw_dist2d_pt_pt(const POINT2D *thep1, const POINT2D *thep2, DISTPTS *dl)
Compares incoming points and stores the points closest to each other or most far away from each other...
Definition: measures.c:2274
static int lw_dist2d_circle_intersections(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, const POINT2D *center_A, double radius_A, const POINT2D *P, POINT2D *I, uint32_t *ni)
Calculates the intersection points of a circle and line.
Definition: measures.c:1566
#define DIST_MIN
Definition: measures.h:44
int mode
Definition: measures.h:54

References DIST_MIN, distance2d_pt_pt(), lw_arc_center(), lw_arc_is_pt(), lw_dist2d_circle_circle_intersections(), lw_dist2d_circle_intersections(), lw_dist2d_distpts_set(), lw_dist2d_pt_arc(), lw_dist2d_pt_pt(), lw_dist2d_seg_arc(), lw_dist2d_seg_seg(), lw_pt_in_arc(), LW_TRUE, lwerror(), DISTPTS::mode, and p2d_same().

Referenced by lw_dist2d_ptarrayarc_ptarrayarc(), rect_leaf_node_distance(), rect_leaf_node_intersects(), and test_lw_dist2d_arc_arc().

Here is the call graph for this function:
Here is the caller graph for this function: