g2d.c
Go to the documentation of this file.
1 /* Copyright (C) 2013-2016, The Regents of The University of Michigan.
2 All rights reserved.
3 This software was developed in the APRIL Robotics Lab under the
4 direction of Edwin Olson, ebolson@umich.edu. This software may be
5 available under alternative licensing terms; contact the address above.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8 1. Redistributions of source code must retain the above copyright notice, this
9  list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11  this list of conditions and the following disclaimer in the documentation
12  and/or other materials provided with the distribution.
13 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 The views and conclusions contained in the software and documentation are those
24 of the authors and should not be interpreted as representing official policies,
25 either expressed or implied, of the Regents of The University of Michigan.
26 */
27 
28 #include <assert.h>
29 #include <math.h>
30 #include <stdio.h>
31 #include <string.h>
32 
33 #include "g2d.h"
34 #include "common/math_util.h"
35 
36 #ifdef _WIN32
37 static inline long int random(void)
38 {
39  return rand();
40 }
41 #endif
42 
43 double g2d_distance(const double a[2], const double b[2])
44 {
45  return sqrtf(sq(a[0]-b[0]) + sq(a[1]-b[1]));
46 }
47 
49 {
50  return zarray_create(sizeof(double[2]));
51 }
52 
53 void g2d_polygon_add(zarray_t *poly, double v[2])
54 {
55  zarray_add(poly, v);
56 }
57 
58 zarray_t *g2d_polygon_create_data(double v[][2], int sz)
59 {
61 
62  for (int i = 0; i < sz; i++)
63  g2d_polygon_add(points, v[i]);
64 
65  return points;
66 }
67 
69 {
70  zarray_t *points = zarray_create(sizeof(double[2]));
71 
72  double z[2] = { 0, 0 };
73 
74  for (int i = 0; i < sz; i++)
75  zarray_add(points, z);
76 
77  return points;
78 }
79 
81 {
82  // Step one: we want the points in counter-clockwise order.
83  // If the points are in clockwise order, we'll reverse them.
84  double total_theta = 0;
85  double last_theta = 0;
86 
87  // Count the angle accumulated going around the polygon. If
88  // the sum is +2pi, it's CCW. Otherwise, we'll get -2pi.
89  int sz = zarray_size(poly);
90 
91  for (int i = 0; i <= sz; i++) {
92  double p0[2], p1[2];
93  zarray_get(poly, i % sz, &p0);
94  zarray_get(poly, (i+1) % sz, &p1);
95 
96  double this_theta = atan2(p1[1]-p0[1], p1[0]-p0[0]);
97 
98  if (i > 0) {
99  double dtheta = mod2pi(this_theta-last_theta);
100  total_theta += dtheta;
101  }
102 
103  last_theta = this_theta;
104  }
105 
106  int ccw = (total_theta > 0);
107 
108  // reverse order if necessary.
109  if (!ccw) {
110  for (int i = 0; i < sz / 2; i++) {
111  double a[2], b[2];
112 
113  zarray_get(poly, i, a);
114  zarray_get(poly, sz-1-i, b);
115  zarray_set(poly, i, b, NULL);
116  zarray_set(poly, sz-1-i, a, NULL);
117  }
118  }
119 }
120 
121 int g2d_polygon_contains_point_ref(const zarray_t *poly, double q[2])
122 {
123  // use winding. If the point is inside the polygon, we'll wrap
124  // around it (accumulating 6.28 radians). If we're outside the
125  // polygon, we'll accumulate zero.
126  int psz = zarray_size(poly);
127 
128  double acc_theta = 0;
129 
130  double last_theta;
131 
132  for (int i = 0; i <= psz; i++) {
133  double p[2];
134 
135  zarray_get(poly, i % psz, &p);
136 
137  double this_theta = atan2(q[1]-p[1], q[0]-p[0]);
138 
139  if (i != 0)
140  acc_theta += mod2pi(this_theta - last_theta);
141 
142  last_theta = this_theta;
143  }
144 
145  return acc_theta > M_PI;
146 }
147 
148 /*
149 // sort by x coordinate, ascending
150 static int g2d_convex_hull_sort(const void *_a, const void *_b)
151 {
152  double *a = (double*) _a;
153  double *b = (double*) _b;
154 
155  if (a[0] < b[0])
156  return -1;
157  if (a[0] == b[0])
158  return 0;
159  return 1;
160 }
161 */
162 
163 /*
164 zarray_t *g2d_convex_hull2(const zarray_t *points)
165 {
166  zarray_t *hull = zarray_copy(points);
167 
168  zarray_sort(hull, g2d_convex_hull_sort);
169 
170  int hsz = zarray_size(hull);
171  int hout = 0;
172 
173  for (int hin = 1; hin < hsz; hin++) {
174  double *p;
175  zarray_get_volatile(hull, i, &p);
176 
177  // Everything to the right of hin is already convex. We now
178  // add one point, p, which begins "connected" by two
179  // (coincident) edges from the last right-most point to p.
180  double *last;
181  zarray_get_volatile(hull, hout, &last);
182 
183  // We now remove points from the convex hull by moving
184  }
185 
186  return hull;
187 }
188 */
189 
190 // creates and returns a zarray(double[2]). The resulting polygon is
191 // CCW and implicitly closed. Unnecessary colinear points are omitted.
193 {
194  zarray_t *hull = zarray_create(sizeof(double[2]));
195 
196  // gift-wrap algorithm.
197 
198  // step 1: find left most point.
199  int insz = zarray_size(points);
200 
201  // must have at least 2 points. (XXX need 3?)
202  assert(insz >= 2);
203 
204  double *pleft = NULL;
205  for (int i = 0; i < insz; i++) {
206  double *p;
207  zarray_get_volatile(points, i, &p);
208 
209  if (pleft == NULL || p[0] < pleft[0])
210  pleft = p;
211  }
212 
213  // cannot be NULL since there must be at least one point.
214  assert(pleft != NULL);
215 
216  zarray_add(hull, pleft);
217 
218  // step 2. gift wrap. Keep searching for points that make the
219  // smallest-angle left-hand turn. This implementation is carefully
220  // written to use only addition/subtraction/multiply. No division
221  // or sqrts. This guarantees exact results for integer-coordinate
222  // polygons (no rounding/precision problems).
223  double *p = pleft;
224 
225  while (1) {
226  assert(p != NULL);
227 
228  double *q = NULL;
229  double n0 = 0, n1 = 0; // the normal to the line (p, q) (not
230  // necessarily unit length).
231 
232  // Search for the point q for which the line (p,q) is most "to
233  // the right of" the other points. (i.e., every time we find a
234  // point that is to the right of our current line, we change
235  // lines.)
236  for (int i = 0; i < insz; i++) {
237  double *thisq;
238  zarray_get_volatile(points, i, &thisq);
239 
240  if (thisq == p)
241  continue;
242 
243  // the first time we find another point, we initialize our
244  // value of q, forming the line (p,q)
245  if (q == NULL) {
246  q = thisq;
247  n0 = q[1] - p[1];
248  n1 = -q[0] + p[0];
249  } else {
250  // we already have a line (p,q). is point thisq RIGHT OF line (p, q)?
251  double e0 = thisq[0] - p[0], e1 = thisq[1] - p[1];
252  double dot = e0*n0 + e1*n1;
253 
254  if (dot > 0) {
255  // it is. change our line.
256  q = thisq;
257  n0 = q[1] - p[1];
258  n1 = -q[0] + p[0];
259  }
260  }
261  }
262 
263  // we must have elected *some* line, so long as there are at
264  // least 2 points in the polygon.
265  assert(q != NULL);
266 
267  // loop completed?
268  if (q == pleft)
269  break;
270 
271  int colinear = 0;
272 
273  // is this new point colinear with the last two?
274  if (zarray_size(hull) > 1) {
275  double *o;
276  zarray_get_volatile(hull, zarray_size(hull) - 2, &o);
277 
278  double e0 = o[0] - p[0];
279  double e1 = o[1] - p[1];
280 
281  if (n0*e0 + n1*e1 == 0)
282  colinear = 1;
283  }
284 
285  // if it is colinear, overwrite the last one.
286  if (colinear)
287  zarray_set(hull, zarray_size(hull)-1, q, NULL);
288  else
289  zarray_add(hull, q);
290 
291  p = q;
292  }
293 
294  return hull;
295 }
296 
297 // Find point p on the boundary of poly that is closest to q.
298 void g2d_polygon_closest_boundary_point(const zarray_t *poly, const double q[2], double *p)
299 {
300  int psz = zarray_size(poly);
301  double min_dist = HUGE_VALF;
302 
303  for (int i = 0; i < psz; i++) {
304  double *p0, *p1;
305 
306  zarray_get_volatile(poly, i, &p0);
307  zarray_get_volatile(poly, (i+1) % psz, &p1);
308 
309  g2d_line_segment_t seg;
310  g2d_line_segment_init_from_points(&seg, p0, p1);
311 
312  double thisp[2];
313  g2d_line_segment_closest_point(&seg, q, thisp);
314 
315  double dist = g2d_distance(q, thisp);
316  if (dist < min_dist) {
317  memcpy(p, thisp, sizeof(double[2]));
318  min_dist = dist;
319  }
320  }
321 }
322 
323 int g2d_polygon_contains_point(const zarray_t *poly, double q[2])
324 {
325  // use winding. If the point is inside the polygon, we'll wrap
326  // around it (accumulating 6.28 radians). If we're outside the
327  // polygon, we'll accumulate zero.
328  int psz = zarray_size(poly);
329  assert(psz > 0);
330 
331  int last_quadrant;
332  int quad_acc = 0;
333 
334  for (int i = 0; i <= psz; i++) {
335  double *p;
336 
337  zarray_get_volatile(poly, i % psz, &p);
338 
339  // p[0] < q[0] p[1] < q[1] quadrant
340  // 0 0 0
341  // 0 1 3
342  // 1 0 1
343  // 1 1 2
344 
345  // p[1] < q[1] p[0] < q[0] quadrant
346  // 0 0 0
347  // 0 1 1
348  // 1 0 3
349  // 1 1 2
350 
351  int quadrant;
352  if (p[0] < q[0])
353  quadrant = (p[1] < q[1]) ? 2 : 1;
354  else
355  quadrant = (p[1] < q[1]) ? 3 : 0;
356 
357  if (i > 0) {
358  int dquadrant = quadrant - last_quadrant;
359 
360  // encourage a jump table by mapping to small positive integers.
361  switch (dquadrant) {
362  case -3:
363  case 1:
364  quad_acc ++;
365  break;
366  case -1:
367  case 3:
368  quad_acc --;
369  break;
370  case 0:
371  break;
372  case -2:
373  case 2:
374  {
375  // get the previous point.
376  double *p0;
377  zarray_get_volatile(poly, i-1, &p0);
378 
379  // Consider the points p0 and p (the points around the
380  //polygon that we are tracing) and the query point q.
381  //
382  // If we've moved diagonally across quadrants, we want
383  // to measure whether we have rotated +PI radians or
384  // -PI radians. We can test this by computing the dot
385  // product of vector (p0-q) with the vector
386  // perpendicular to vector (p-q)
387  double nx = p[1] - q[1];
388  double ny = -p[0] + q[0];
389 
390  double dot = nx*(p0[0]-q[0]) + ny*(p0[1]-q[1]);
391  if (dot < 0)
392  quad_acc -= 2;
393  else
394  quad_acc += 2;
395 
396  break;
397  }
398  }
399  }
400 
401  last_quadrant = quadrant;
402  }
403 
404  int v = (quad_acc >= 2) || (quad_acc <= -2);
405 
406  #if 0
407  if (v != g2d_polygon_contains_point_ref(poly, q)) {
408  printf("FAILURE %d %d\n", v, quad_acc);
409  exit(-1);
410  }
411  #endif
412 
413  return v;
414 }
415 
416 void g2d_line_init_from_points(g2d_line_t *line, const double p0[2], const double p1[2])
417 {
418  line->p[0] = p0[0];
419  line->p[1] = p0[1];
420  line->u[0] = p1[0]-p0[0];
421  line->u[1] = p1[1]-p0[1];
422  double mag = sqrtf(sq(line->u[0]) + sq(line->u[1]));
423 
424  line->u[0] /= mag;
425  line->u[1] /= mag;
426 }
427 
428 double g2d_line_get_coordinate(const g2d_line_t *line, const double q[2])
429 {
430  return (q[0]-line->p[0])*line->u[0] + (q[1]-line->p[1])*line->u[1];
431 }
432 
433 // Compute intersection of two line segments. If they intersect,
434 // result is stored in p and 1 is returned. Otherwise, zero is
435 // returned. p may be NULL.
436 int g2d_line_intersect_line(const g2d_line_t *linea, const g2d_line_t *lineb, double *p)
437 {
438  // this implementation is many times faster than the original,
439  // mostly due to avoiding a general-purpose LU decomposition in
440  // Matrix.inverse().
441  double m00, m01, m10, m11;
442  double i00, i01;
443  double b00, b10;
444 
445  m00 = linea->u[0];
446  m01= -lineb->u[0];
447  m10 = linea->u[1];
448  m11= -lineb->u[1];
449 
450  // determinant of m
451  double det = m00*m11-m01*m10;
452 
453  // parallel lines?
454  if (fabs(det) < 0.00000001)
455  return 0;
456 
457  // inverse of m
458  i00 = m11/det;
459  i01 = -m01/det;
460 
461  b00 = lineb->p[0] - linea->p[0];
462  b10 = lineb->p[1] - linea->p[1];
463 
464  double x00; //, x10;
465  x00 = i00*b00+i01*b10;
466 
467  if (p != NULL) {
468  p[0] = linea->u[0]*x00 + linea->p[0];
469  p[1] = linea->u[1]*x00 + linea->p[1];
470  }
471 
472  return 1;
473 }
474 
475 
476 void g2d_line_segment_init_from_points(g2d_line_segment_t *seg, const double p0[2], const double p1[2])
477 {
478  g2d_line_init_from_points(&seg->line, p0, p1);
479  seg->p1[0] = p1[0];
480  seg->p1[1] = p1[1];
481 }
482 
483 // Find the point p on segment seg that is closest to point q.
484 void g2d_line_segment_closest_point(const g2d_line_segment_t *seg, const double *q, double *p)
485 {
486  double a = g2d_line_get_coordinate(&seg->line, seg->line.p);
487  double b = g2d_line_get_coordinate(&seg->line, seg->p1);
488  double c = g2d_line_get_coordinate(&seg->line, q);
489 
490  if (a < b)
491  c = dclamp(c, a, b);
492  else
493  c = dclamp(c, b, a);
494 
495  p[0] = seg->line.p[0] + c * seg->line.u[0];
496  p[1] = seg->line.p[1] + c * seg->line.u[1];
497 }
498 
499 // Compute intersection of two line segments. If they intersect,
500 // result is stored in p and 1 is returned. Otherwise, zero is
501 // returned. p may be NULL.
503 {
504  double tmp[2];
505 
506  if (!g2d_line_intersect_line(&sega->line, &segb->line, tmp))
507  return 0;
508 
509  double a = g2d_line_get_coordinate(&sega->line, sega->line.p);
510  double b = g2d_line_get_coordinate(&sega->line, sega->p1);
511  double c = g2d_line_get_coordinate(&sega->line, tmp);
512 
513  // does intersection lie on the first line?
514  if ((c<a && c<b) || (c>a && c>b))
515  return 0;
516 
517  a = g2d_line_get_coordinate(&segb->line, segb->line.p);
518  b = g2d_line_get_coordinate(&segb->line, segb->p1);
519  c = g2d_line_get_coordinate(&segb->line, tmp);
520 
521  // does intersection lie on second line?
522  if ((c<a && c<b) || (c>a && c>b))
523  return 0;
524 
525  if (p != NULL) {
526  p[0] = tmp[0];
527  p[1] = tmp[1];
528  }
529 
530  return 1;
531 }
532 
533 // Compute intersection of a line segment and a line. If they
534 // intersect, result is stored in p and 1 is returned. Otherwise, zero
535 // is returned. p may be NULL.
536 int g2d_line_segment_intersect_line(const g2d_line_segment_t *seg, const g2d_line_t *line, double *p)
537 {
538  double tmp[2];
539 
540  if (!g2d_line_intersect_line(&seg->line, line, tmp))
541  return 0;
542 
543  double a = g2d_line_get_coordinate(&seg->line, seg->line.p);
544  double b = g2d_line_get_coordinate(&seg->line, seg->p1);
545  double c = g2d_line_get_coordinate(&seg->line, tmp);
546 
547  // does intersection lie on the first line?
548  if ((c<a && c<b) || (c>a && c>b))
549  return 0;
550 
551  if (p != NULL) {
552  p[0] = tmp[0];
553  p[1] = tmp[1];
554  }
555 
556  return 1;
557 }
558 
559 // do the edges of polya and polyb collide? (Does NOT test for containment).
560 int g2d_polygon_intersects_polygon(const zarray_t *polya, const zarray_t *polyb)
561 {
562  // do any of the line segments collide? If so, the answer is no.
563 
564  // dumb N^2 method.
565  for (int ia = 0; ia < zarray_size(polya); ia++) {
566  double pa0[2], pa1[2];
567  zarray_get(polya, ia, pa0);
568  zarray_get(polya, (ia+1)%zarray_size(polya), pa1);
569 
570  g2d_line_segment_t sega;
571  g2d_line_segment_init_from_points(&sega, pa0, pa1);
572 
573  for (int ib = 0; ib < zarray_size(polyb); ib++) {
574  double pb0[2], pb1[2];
575  zarray_get(polyb, ib, pb0);
576  zarray_get(polyb, (ib+1)%zarray_size(polyb), pb1);
577 
578  g2d_line_segment_t segb;
579  g2d_line_segment_init_from_points(&segb, pb0, pb1);
580 
581  if (g2d_line_segment_intersect_segment(&sega, &segb, NULL))
582  return 1;
583  }
584  }
585 
586  return 0;
587 }
588 
589 // does polya completely contain polyb?
590 int g2d_polygon_contains_polygon(const zarray_t *polya, const zarray_t *polyb)
591 {
592  // do any of the line segments collide? If so, the answer is no.
593  if (g2d_polygon_intersects_polygon(polya, polyb))
594  return 0;
595 
596  // if none of the edges cross, then the polygon is either fully
597  // contained or fully outside.
598  double p[2];
599  zarray_get(polyb, 0, p);
600 
601  return g2d_polygon_contains_point(polya, p);
602 }
603 
604 // compute a point that is inside the polygon. (It may not be *far* inside though)
605 void g2d_polygon_get_interior_point(const zarray_t *poly, double *p)
606 {
607  // take the first three points, which form a triangle. Find the middle point
608  double a[2], b[2], c[2];
609 
610  zarray_get(poly, 0, a);
611  zarray_get(poly, 1, b);
612  zarray_get(poly, 2, c);
613 
614  p[0] = (a[0]+b[0]+c[0])/3;
615  p[1] = (a[1]+b[1]+c[1])/3;
616 }
617 
618 int g2d_polygon_overlaps_polygon(const zarray_t *polya, const zarray_t *polyb)
619 {
620  // do any of the line segments collide? If so, the answer is yes.
621  if (g2d_polygon_intersects_polygon(polya, polyb))
622  return 1;
623 
624  // if none of the edges cross, then the polygon is either fully
625  // contained or fully outside.
626  double p[2];
628 
629  if (g2d_polygon_contains_point(polya, p))
630  return 1;
631 
633 
634  if (g2d_polygon_contains_point(polyb, p))
635  return 1;
636 
637  return 0;
638 }
639 
640 static int double_sort_up(const void *_a, const void *_b)
641 {
642  double a = *((double*) _a);
643  double b = *((double*) _b);
644 
645  if (a < b)
646  return -1;
647 
648  if (a == b)
649  return 0;
650 
651  return 1;
652 }
653 
654 // Compute the crossings of the polygon along line y, storing them in
655 // the array x. X must be allocated to be at least as long as
656 // zarray_size(poly). X will be sorted, ready for
657 // rasterization. Returns the number of intersections (and elements
658 // written to x).
659 /*
660  To rasterize, do something like this:
661 
662  double res = 0.099;
663  for (double y = y0; y < y1; y += res) {
664  double xs[zarray_size(poly)];
665 
666  int xsz = g2d_polygon_rasterize(poly, y, xs);
667  int xpos = 0;
668  int inout = 0; // start off "out"
669 
670  for (double x = x0; x < x1; x += res) {
671  while (x > xs[xpos] && xpos < xsz) {
672  xpos++;
673  inout ^= 1;
674  }
675 
676  if (inout)
677  printf("y");
678  else
679  printf(" ");
680  }
681  printf("\n");
682 */
683 
684 // returns the number of x intercepts
685 int g2d_polygon_rasterize(const zarray_t *poly, double y, double *x)
686 {
687  int sz = zarray_size(poly);
688 
689  g2d_line_t line;
690  if (1) {
691  double p0[2] = { 0, y };
692  double p1[2] = { 1, y };
693 
694  g2d_line_init_from_points(&line, p0, p1);
695  }
696 
697  int xpos = 0;
698 
699  for (int i = 0; i < sz; i++) {
700  g2d_line_segment_t seg;
701  double *p0, *p1;
702  zarray_get_volatile(poly, i, &p0);
703  zarray_get_volatile(poly, (i+1)%sz, &p1);
704 
705  g2d_line_segment_init_from_points(&seg, p0, p1);
706 
707  double q[2];
708  if (g2d_line_segment_intersect_line(&seg, &line, q))
709  x[xpos++] = q[0];
710  }
711 
712  qsort(x, xpos, sizeof(double), double_sort_up);
713 
714  return xpos;
715 }
716 
717 /*
718  /---(1,5)
719  (-2,4)-/ |
720  \ |
721  \ (1,2)--(2,2)\
722  \ \
723  \ \
724  (0,0)------------------(4,0)
725 */
726 #if 0
727 
728 #include "timeprofile.h"
729 
730 int main(int argc, char *argv[])
731 {
733 
734  zarray_t *polya = g2d_polygon_create_data((double[][2]) {
735  { 0, 0},
736  { 4, 0},
737  { 2, 2},
738  { 1, 2},
739  { 1, 5},
740  { -2,4} }, 6);
741 
742  zarray_t *polyb = g2d_polygon_create_data((double[][2]) {
743  { .1, .1},
744  { .5, .1},
745  { .1, .5 } }, 3);
746 
747  zarray_t *polyc = g2d_polygon_create_data((double[][2]) {
748  { 3, 0},
749  { 5, 0},
750  { 5, 1} }, 3);
751 
752  zarray_t *polyd = g2d_polygon_create_data((double[][2]) {
753  { 5, 5},
754  { 6, 6},
755  { 5, 6} }, 3);
756 
757 /*
758  5 L---K
759  4 |I--J
760  3 |H-G
761  2 |E-F
762  1 |D--C
763  0 A---B
764  01234
765 */
766  zarray_t *polyE = g2d_polygon_create_data((double[][2]) {
767  {0,0}, {4,0}, {4, 1}, {1,1},
768  {1,2}, {3,2}, {3,3}, {1,3},
769  {1,4}, {4,4}, {4,5}, {0,5}}, 12);
770 
771  srand(0);
772 
773  timeprofile_stamp(tp, "begin");
774 
775  if (1) {
776  int niters = 100000;
777 
778  for (int i = 0; i < niters; i++) {
779  double q[2];
780  q[0] = 10.0f * random() / RAND_MAX - 2;
781  q[1] = 10.0f * random() / RAND_MAX - 2;
782 
783  g2d_polygon_contains_point(polyE, q);
784  }
785 
786  timeprofile_stamp(tp, "fast");
787 
788  for (int i = 0; i < niters; i++) {
789  double q[2];
790  q[0] = 10.0f * random() / RAND_MAX - 2;
791  q[1] = 10.0f * random() / RAND_MAX - 2;
792 
794  }
795 
796  timeprofile_stamp(tp, "slow");
797 
798  for (int i = 0; i < niters; i++) {
799  double q[2];
800  q[0] = 10.0f * random() / RAND_MAX - 2;
801  q[1] = 10.0f * random() / RAND_MAX - 2;
802 
803  int v0 = g2d_polygon_contains_point(polyE, q);
804  int v1 = g2d_polygon_contains_point_ref(polyE, q);
805  assert(v0 == v1);
806  }
807 
808  timeprofile_stamp(tp, "both");
810  }
811 
812  if (1) {
813  zarray_t *poly = polyE;
814 
815  double res = 0.399;
816  for (double y = 5.2; y >= -.5; y -= res) {
817  double xs[zarray_size(poly)];
818 
819  int xsz = g2d_polygon_rasterize(poly, y, xs);
820  int xpos = 0;
821  int inout = 0; // start off "out"
822  for (double x = -3; x < 6; x += res) {
823  while (x > xs[xpos] && xpos < xsz) {
824  xpos++;
825  inout ^= 1;
826  }
827 
828  if (inout)
829  printf("y");
830  else
831  printf(" ");
832  }
833  printf("\n");
834 
835  for (double x = -3; x < 6; x += res) {
836  double q[2] = {x, y};
837  if (g2d_polygon_contains_point(poly, q))
838  printf("X");
839  else
840  printf(" ");
841  }
842  printf("\n");
843  }
844  }
845 
846 
847 
848 /*
849 // CW order
850 double p[][2] = { { 0, 0},
851 { -2, 4},
852 {1, 5},
853 {1, 2},
854 {2, 2},
855 {4, 0} };
856 */
857 
858  double q[2] = { 10, 10 };
859  printf("0==%d\n", g2d_polygon_contains_point(polya, q));
860 
861  q[0] = 1; q[1] = 1;
862  printf("1==%d\n", g2d_polygon_contains_point(polya, q));
863 
864  q[0] = 3; q[1] = .5;
865  printf("1==%d\n", g2d_polygon_contains_point(polya, q));
866 
867  q[0] = 1.2; q[1] = 2.1;
868  printf("0==%d\n", g2d_polygon_contains_point(polya, q));
869 
870  printf("0==%d\n", g2d_polygon_contains_polygon(polya, polyb));
871 
872  printf("0==%d\n", g2d_polygon_contains_polygon(polya, polyc));
873 
874  printf("0==%d\n", g2d_polygon_contains_polygon(polya, polyd));
875 
877  // Test convex hull
878  if (1) {
879  zarray_t *hull = g2d_convex_hull(polyE);
880 
881  for (int k = 0; k < zarray_size(hull); k++) {
882  double *h;
883  zarray_get_volatile(hull, k, &h);
884 
885  printf("%15f, %15f\n", h[0], h[1]);
886  }
887  }
888 
889  for (int i = 0; i < 100000; i++) {
890  zarray_t *points = zarray_create(sizeof(double[2]));
891 
892  for (int j = 0; j < 100; j++) {
893  double q[2];
894  q[0] = 10.0f * random() / RAND_MAX - 2;
895  q[1] = 10.0f * random() / RAND_MAX - 2;
896 
897  zarray_add(points, q);
898  }
899 
900  zarray_t *hull = g2d_convex_hull(points);
901  for (int j = 0; j < zarray_size(points); j++) {
902  double *q;
903  zarray_get_volatile(points, j, &q);
904 
905  int on_edge;
906 
907  double p[2];
909  if (g2d_distance(q, p) < .00001)
910  on_edge = 1;
911 
912  assert(on_edge || g2d_polygon_contains_point(hull, q));
913  }
914 
915  zarray_destroy(hull);
916  zarray_destroy(points);
917  }
918 }
919 #endif
int g2d_polygon_intersects_polygon(const zarray_t *polya, const zarray_t *polyb)
Definition: g2d.c:560
void g2d_polygon_get_interior_point(const zarray_t *poly, double *p)
Definition: g2d.c:605
int g2d_line_intersect_line(const g2d_line_t *linea, const g2d_line_t *lineb, double *p)
Definition: g2d.c:436
static void zarray_get_volatile(const zarray_t *za, int idx, void *p)
Definition: zarray.h:212
double g2d_line_get_coordinate(const g2d_line_t *line, const double q[2])
Definition: g2d.c:428
static void timeprofile_stamp(timeprofile_t *tp, const char *name)
Definition: timeprofile.h:76
void g2d_polygon_closest_boundary_point(const zarray_t *poly, const double q[2], double *p)
Definition: g2d.c:298
static int zarray_size(const zarray_t *za)
Definition: zarray.h:130
static int double_sort_up(const void *_a, const void *_b)
Definition: g2d.c:640
static void zarray_destroy(zarray_t *za)
Definition: zarray.h:70
static void zarray_set(zarray_t *za, int idx, const void *p, void *outp)
Definition: zarray.h:319
void g2d_line_segment_init_from_points(g2d_line_segment_t *seg, const double p0[2], const double p1[2])
Definition: g2d.c:476
static void timeprofile_display(timeprofile_t *tp)
Definition: timeprofile.h:87
int g2d_line_segment_intersect_line(const g2d_line_segment_t *seg, const g2d_line_t *line, double *p)
Definition: g2d.c:536
static double mod2pi(double vin)
Definition: math_util.h:118
zarray_t * g2d_polygon_create_data(double v[][2], int sz)
Definition: g2d.c:58
int g2d_polygon_contains_point(const zarray_t *poly, double q[2])
Definition: g2d.c:323
zarray_t * g2d_polygon_create_zeros(int sz)
Definition: g2d.c:68
static zarray_t * zarray_create(size_t el_sz)
Definition: zarray.h:57
float p[4][2]
Definition: apriltag.h:47
int g2d_polygon_overlaps_polygon(const zarray_t *polya, const zarray_t *polyb)
Definition: g2d.c:618
g2d_line_t line
Definition: g2d.h:79
int g2d_polygon_contains_point_ref(const zarray_t *poly, double q[2])
Definition: g2d.c:121
double g2d_distance(const double a[2], const double b[2])
Definition: g2d.c:43
int g2d_line_segment_intersect_segment(const g2d_line_segment_t *sega, const g2d_line_segment_t *segb, double *p)
Definition: g2d.c:502
zarray_t * g2d_convex_hull(const zarray_t *points)
Definition: g2d.c:192
static double sq(double v)
Definition: math_util.h:78
static timeprofile_t * timeprofile_create()
Definition: timeprofile.h:54
zarray_t * g2d_polygon_create_empty()
Definition: g2d.c:48
double u[2]
Definition: g2d.h:59
double p[2]
Definition: g2d.h:58
double p1[2]
Definition: g2d.h:80
static void zarray_get(const zarray_t *za, int idx, void *p)
Definition: zarray.h:195
Definition: zarray.h:43
void g2d_polygon_make_ccw(zarray_t *poly)
Definition: g2d.c:80
static double dclamp(double a, double min, double max)
Definition: math_util.h:183
void g2d_line_segment_closest_point(const g2d_line_segment_t *seg, const double *q, double *p)
Definition: g2d.c:484
int main(int argc, char *argv[])
Definition: apriltag_demo.c:61
int g2d_polygon_contains_polygon(const zarray_t *polya, const zarray_t *polyb)
Definition: g2d.c:590
Definition: g2d.h:54
void g2d_polygon_add(zarray_t *poly, double v[2])
Definition: g2d.c:53
int g2d_polygon_rasterize(const zarray_t *poly, double y, double *x)
Definition: g2d.c:685
void g2d_line_init_from_points(g2d_line_t *line, const double p0[2], const double p1[2])
Definition: g2d.c:416
#define M_PI
Definition: math_util.h:46
static void zarray_add(zarray_t *za, const void *p)
Definition: zarray.h:179


apriltag
Author(s): Edwin Olson , Max Krogius
autogenerated on Mon Jun 26 2023 02:26:12