PostGIS  2.3.8dev-r@@SVN_REVISION@@

◆ lwcircle_stroke()

static POINTARRAY* lwcircle_stroke ( const POINT4D p1,
const POINT4D p2,
const POINT4D p3,
uint32_t  perQuad 
)
static

Definition at line 118 of file lwstroke.c.

References interpolate_arc(), lw_arc_center(), LW_FALSE, lw_segment_side(), LW_TRUE, LWDEBUG, POINT4D::m, ptarray_append_point(), ptarray_construct_empty(), POINT2D::x, POINT4D::x, POINT2D::y, POINT4D::y, and POINT4D::z.

Referenced by lwcircstring_stroke().

119 {
120  POINT2D center;
121  POINT2D *t1 = (POINT2D*)p1;
122  POINT2D *t2 = (POINT2D*)p2;
123  POINT2D *t3 = (POINT2D*)p3;
124  POINT4D pt;
125  int p2_side = 0;
126  int clockwise = LW_TRUE;
127  double radius; /* Arc radius */
128  double increment; /* Angle per segment */
129  double a1, a2, a3, angle;
130  POINTARRAY *pa;
131  int is_circle = LW_FALSE;
132 
133  LWDEBUG(2, "lwcircle_calculate_gbox called.");
134 
135  radius = lw_arc_center(t1, t2, t3, &center);
136  p2_side = lw_segment_side(t1, t3, t2);
137 
138  /* Matched start/end points imply circle */
139  if ( p1->x == p3->x && p1->y == p3->y )
140  is_circle = LW_TRUE;
141 
142  /* Negative radius signals straight line, p1/p2/p3 are colinear */
143  if ( (radius < 0.0 || p2_side == 0) && ! is_circle )
144  return NULL;
145 
146  /* The side of the p1/p3 line that p2 falls on dictates the sweep
147  direction from p1 to p3. */
148  if ( p2_side == -1 )
149  clockwise = LW_TRUE;
150  else
151  clockwise = LW_FALSE;
152 
153  increment = fabs(M_PI_2 / perQuad);
154 
155  /* Angles of each point that defines the arc section */
156  a1 = atan2(p1->y - center.y, p1->x - center.x);
157  a2 = atan2(p2->y - center.y, p2->x - center.x);
158  a3 = atan2(p3->y - center.y, p3->x - center.x);
159 
160  /* p2 on left side => clockwise sweep */
161  if ( clockwise )
162  {
163  increment *= -1;
164  /* Adjust a3 down so we can decrement from a1 to a3 cleanly */
165  if ( a3 > a1 )
166  a3 -= 2.0 * M_PI;
167  if ( a2 > a1 )
168  a2 -= 2.0 * M_PI;
169  }
170  /* p2 on right side => counter-clockwise sweep */
171  else
172  {
173  /* Adjust a3 up so we can increment from a1 to a3 cleanly */
174  if ( a3 < a1 )
175  a3 += 2.0 * M_PI;
176  if ( a2 < a1 )
177  a2 += 2.0 * M_PI;
178  }
179 
180  /* Override angles for circle case */
181  if( is_circle )
182  {
183  a3 = a1 + 2.0 * M_PI;
184  a2 = a1 + M_PI;
185  increment = fabs(increment);
186  clockwise = LW_FALSE;
187  }
188 
189  /* Initialize point array */
190  pa = ptarray_construct_empty(1, 1, 32);
191 
192  /* Sweep from a1 to a3 */
194  for ( angle = a1 + increment; clockwise ? angle > a3 : angle < a3; angle += increment )
195  {
196  pt.x = center.x + radius * cos(angle);
197  pt.y = center.y + radius * sin(angle);
198  pt.z = interpolate_arc(angle, a1, a2, a3, p1->z, p2->z, p3->z);
199  pt.m = interpolate_arc(angle, a1, a2, a3, p1->m, p2->m, p3->m);
200  ptarray_append_point(pa, &pt, LW_FALSE);
201  }
202  return pa;
203 }
double x
Definition: liblwgeom.h:351
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:227
double m
Definition: liblwgeom.h:351
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:70
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
double x
Definition: liblwgeom.h:327
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE, then a duplicate point will not be added.
Definition: ptarray.c:156
#define LW_FALSE
Definition: liblwgeom.h:76
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:75
double y
Definition: liblwgeom.h:327
static double interpolate_arc(double angle, double a1, double a2, double a3, double zm1, double zm2, double zm3)
Definition: lwstroke.c:96
double z
Definition: liblwgeom.h:351
int lw_segment_side(const POINT2D *p1, const POINT2D *p2, const POINT2D *q)
lw_segment_side()
Definition: lwalgorithm.c:64
double y
Definition: liblwgeom.h:351
Here is the call graph for this function:
Here is the caller graph for this function: