PostGIS  3.6.1dev-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 1677 of file measures.c.

1681 {
1682  POINT2D pts_A[16]; /* Points on A that might be the nearest */
1683  POINT2D pts_B[16]; /* Points on B that might be the nearest */
1684  uint32_t ai = 0, bi = 0; /* Number of points in pts_A and pts_B */
1685  POINT2D center_A, center_B; /* Center points of arcs A and B */
1686  double radius_A, radius_B, d; /* Radii of arcs A and B */
1687  int is_disjoint, is_overlapping, is_contained, is_same_center;
1688  POINT2D intersectionPts[2];
1689 
1690  if (dl->mode != DIST_MIN)
1691  lwerror("lw_dist2d_arc_arc only supports mindistance");
1692 
1693  /* What if one or both of our "arcs" is actually a point? */
1694  if (lw_arc_is_pt(B1, B2, B3) && lw_arc_is_pt(A1, A2, A3))
1695  return lw_dist2d_pt_pt(B1, A1, dl);
1696  else if (lw_arc_is_pt(B1, B2, B3))
1697  return lw_dist2d_pt_arc(B1, A1, A2, A3, dl);
1698  else if (lw_arc_is_pt(A1, A2, A3))
1699  return lw_dist2d_pt_arc(A1, B1, B2, B3, dl);
1700 
1701  /* Calculate centers and radii of circles. */
1702  radius_A = lw_arc_center(A1, A2, A3, &center_A);
1703  radius_B = lw_arc_center(B1, B2, B3, &center_B);
1704 
1705  /* Two co-linear arcs?!? That's two segments. */
1706  if (radius_A < 0 && radius_B < 0)
1707  return lw_dist2d_seg_seg(A1, A3, B1, B3, dl);
1708 
1709  /* A is co-linear, delegate to lw_dist_seg_arc here. */
1710  if (radius_A < 0)
1711  return lw_dist2d_seg_arc(A1, A3, B1, B2, B3, dl);
1712 
1713  /* B is co-linear, delegate to lw_dist_seg_arc here. */
1714  if (radius_B < 0)
1715  return lw_dist2d_seg_arc(B1, B3, A1, A2, A3, dl);
1716 
1717  /* Circle relationships */
1718  d = distance2d_pt_pt(&center_A, &center_B);
1719  is_disjoint = (d > (radius_A + radius_B));
1720  is_contained = (d < fabs(radius_A - radius_B));
1721  is_same_center = p2d_same(&center_A, &center_B);
1722  is_overlapping = ! (is_disjoint || is_contained || is_same_center);
1723 
1724  /*
1725  * Prime the array of potential closest points with the
1726  * arc end points, which frequently participate in closest
1727  * points.
1728  */
1729  pts_A[ai++] = *A1;
1730  pts_A[ai++] = *A3;
1731  pts_B[bi++] = *B1;
1732  pts_B[bi++] = *B3;
1733 
1734  /*
1735  * Overlapping circles might have a zero distance
1736  * case if the circle intersection points are inside both
1737  * arcs.
1738  */
1739  if (is_overlapping)
1740  {
1741  /*
1742  * Find the two points the circles intersect at.
1743  */
1744  uint32_t npoints = lw_dist2d_circle_circle_intersections(
1745  &center_A, radius_A,
1746  &center_B, radius_B,
1747  intersectionPts);
1748  for (uint32_t i = 0; i < npoints; i++)
1749  {
1750  /*
1751  * If an intersection point is contained in both
1752  * arcs, that is a location of zero distance, so
1753  * we are done calculating.
1754  */
1755  if (lw_pt_in_arc(&intersectionPts[i], A1, A2, A3) &&
1756  lw_pt_in_arc(&intersectionPts[i], B1, B2, B3))
1757  {
1758  lw_dist2d_distpts_set(dl, 0.0, &intersectionPts[i], &intersectionPts[i]);
1759  return LW_TRUE;
1760  }
1761  }
1762  }
1763 
1764  /*
1765  * Join the circle centers and find the places that
1766  * line intersects the circles. Where those places
1767  * are in the arcs, they are potential sites of the
1768  * closest points.
1769  */
1770  if (is_disjoint || is_contained || is_overlapping)
1771  {
1772  if (!is_same_center)
1773  {
1774  /* Add points on A that intersect line from center_A to center_B */
1776  A1, A2, A3,
1777  &center_A, radius_A, &center_B,
1778  pts_A, &ai);
1779 
1780  /* Add points on B that intersect line from center_B to center_A */
1782  B1, B2, B3,
1783  &center_B, radius_B, &center_A,
1784  pts_B, &bi);
1785  }
1786 
1787  /* Add points on A that intersect line to B1 */
1789  A1, A2, A3,
1790  &center_A, radius_A, B1,
1791  pts_A, &ai);
1792 
1793  /* Add points on A that intersect line to B3 */
1795  A1, A2, A3,
1796  &center_A, radius_A, B3,
1797  pts_A, &ai);
1798 
1799  /* Add points on B that intersect line to A1 */
1801  B1, B2, B3,
1802  &center_B, radius_B, A1,
1803  pts_B, &bi);
1804 
1805  /* Add points on B that intersect line to A3 */
1807  B1, B2, B3,
1808  &center_B, radius_B, A3,
1809  pts_B, &bi);
1810  }
1811 
1812  /*
1813  * Now just brute force check all pairs of participating
1814  * points, to find the pair that is closest together.
1815  */
1816  for (uint32_t i = 0; i < ai; i++)
1817  for (uint32_t j = 0; j < bi; j++)
1818  lw_dist2d_pt_pt(&pts_A[i], &pts_B[j], dl);
1819 
1820  return LW_TRUE;
1821 }
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:93
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:244
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:121
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:91
int p2d_same(const POINT2D *p1, const POINT2D *p2)
Definition: lwalgorithm.c:57
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
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:2344
int lw_dist2d_pt_arc(const POINT2D *P, const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, DISTPTS *dl)
Definition: measures.c:1495
static void lw_dist2d_distpts_set(DISTPTS *dl, double distance, const POINT2D *p1, const POINT2D *p2)
Definition: measures.c:81
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:1830
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:1351
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:2312
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: