PostGIS  2.2.7dev-r@@SVN_REVISION@@
static POINTARRAY* lwcircle_stroke ( const POINT4D p1,
const POINT4D p2,
const POINT4D p3,
uint32_t  perQuad 
)
static

Definition at line 102 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().

103 {
104  POINT2D center;
105  POINT2D *t1 = (POINT2D*)p1;
106  POINT2D *t2 = (POINT2D*)p2;
107  POINT2D *t3 = (POINT2D*)p3;
108  POINT4D pt;
109  int p2_side = 0;
110  int clockwise = LW_TRUE;
111  double radius; /* Arc radius */
112  double increment; /* Angle per segment */
113  double a1, a2, a3, angle;
114  POINTARRAY *pa;
115  int is_circle = LW_FALSE;
116 
117  LWDEBUG(2, "lwcircle_calculate_gbox called.");
118 
119  radius = lw_arc_center(t1, t2, t3, &center);
120  p2_side = lw_segment_side(t1, t3, t2);
121 
122  /* Matched start/end points imply circle */
123  if ( p1->x == p3->x && p1->y == p3->y )
124  is_circle = LW_TRUE;
125 
126  /* Negative radius signals straight line, p1/p2/p3 are colinear */
127  if ( (radius < 0.0 || p2_side == 0) && ! is_circle )
128  return NULL;
129 
130  /* The side of the p1/p3 line that p2 falls on dictates the sweep
131  direction from p1 to p3. */
132  if ( p2_side == -1 )
133  clockwise = LW_TRUE;
134  else
135  clockwise = LW_FALSE;
136 
137  increment = fabs(M_PI_2 / perQuad);
138 
139  /* Angles of each point that defines the arc section */
140  a1 = atan2(p1->y - center.y, p1->x - center.x);
141  a2 = atan2(p2->y - center.y, p2->x - center.x);
142  a3 = atan2(p3->y - center.y, p3->x - center.x);
143 
144  /* p2 on left side => clockwise sweep */
145  if ( clockwise )
146  {
147  increment *= -1;
148  /* Adjust a3 down so we can decrement from a1 to a3 cleanly */
149  if ( a3 > a1 )
150  a3 -= 2.0 * M_PI;
151  if ( a2 > a1 )
152  a2 -= 2.0 * M_PI;
153  }
154  /* p2 on right side => counter-clockwise sweep */
155  else
156  {
157  /* Adjust a3 up so we can increment from a1 to a3 cleanly */
158  if ( a3 < a1 )
159  a3 += 2.0 * M_PI;
160  if ( a2 < a1 )
161  a2 += 2.0 * M_PI;
162  }
163 
164  /* Override angles for circle case */
165  if( is_circle )
166  {
167  a3 = a1 + 2.0 * M_PI;
168  a2 = a1 + M_PI;
169  increment = fabs(increment);
170  clockwise = LW_FALSE;
171  }
172 
173  /* Initialize point array */
174  pa = ptarray_construct_empty(1, 1, 32);
175 
176  /* Sweep from a1 to a3 */
178  for ( angle = a1 + increment; clockwise ? angle > a3 : angle < a3; angle += increment )
179  {
180  pt.x = center.x + radius * cos(angle);
181  pt.y = center.y + radius * sin(angle);
182  pt.z = interpolate_arc(angle, a1, a2, a3, p1->z, p2->z, p3->z);
183  pt.m = interpolate_arc(angle, a1, a2, a3, p1->m, p2->m, p3->m);
184  ptarray_append_point(pa, &pt, LW_FALSE);
185  }
186  return pa;
187 }
double x
Definition: liblwgeom.h:336
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:213
double m
Definition: liblwgeom.h:336
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:50
double x
Definition: liblwgeom.h:312
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_TRUE, then a duplicate point will not be added.
Definition: ptarray.c:156
#define LW_FALSE
Definition: liblwgeom.h:62
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:61
double y
Definition: liblwgeom.h:312
static double interpolate_arc(double angle, double a1, double a2, double a3, double zm1, double zm2, double zm3)
Definition: lwstroke.c:80
double z
Definition: liblwgeom.h:336
int lw_segment_side(const POINT2D *p1, const POINT2D *p2, const POINT2D *q)
lw_segment_side()
Definition: lwalgorithm.c:50
double y
Definition: liblwgeom.h:336

Here is the call graph for this function:

Here is the caller graph for this function: