21#    define JCV_REAL_TYPE float 
   24#  ifndef JCV_REAL_TYPE_EPSILON 
   25#    define JCV_REAL_TYPE_EPSILON FLT_EPSILON 
   29#    define JCV_ATAN2(_Y_, _X_) atan2f(_Y_, _X_) 
   33#    define JCV_SQRT(_X_) sqrtf(_X_) 
   37#    define JCV_PI 3.14159265358979323846264338327950288f 
   41#    define JCV_FLT_MAX 3.402823466e+38F 
   44#  ifndef JCV_EDGE_INTERSECT_THRESHOLD 
   46#    define JCV_EDGE_INTERSECT_THRESHOLD 1.0e-10F 
   51  typedef JCV_REAL_TYPE jcv_real;
 
   62  typedef struct jcv_context_internal_ jcv_context_internal;
 
   74  typedef void (*jcv_clip_fillgap_fn)(
const jcv_clipper* clipper, jcv_context_internal* allocator, 
jcv_site* s);
 
   86  typedef void* (*FJCVAllocFn)(
void* userctx, 
size_t size);
 
   87  typedef void (*FJCVFreeFn)(
void* userctx, 
void* p);
 
   90  extern void jcv_diagram_generate_useralloc(
int num_points, 
const jcv_point* points, 
const jcv_rect* rect, 
const jcv_clipper* clipper, 
void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, 
jcv_diagram* diagram);
 
  116  extern void jcv_boxshape_fillgaps(
const jcv_clipper* clipper, jcv_context_internal* allocator, 
jcv_site* s);
 
  119#  ifndef JCV_DISABLE_STRUCT_PACKING 
  120#    pragma pack(push, 1) 
  177    jcv_clip_test_point_fn test_fn;
 
  178    jcv_clip_edge_fn clip_fn;
 
  179    jcv_clip_fillgap_fn fill_fn;
 
 
  187    jcv_context_internal* internal;
 
 
  193#  ifndef JCV_DISABLE_STRUCT_PACKING 
  203#ifdef JC_VORONOI_IMPLEMENTATION 
  204#  undef JC_VORONOI_IMPLEMENTATION 
  210#  if defined(_MSC_VER) && !defined(__cplusplus) 
  211#    define inline __inline 
  214static const int JCV_DIRECTION_LEFT = 0;
 
  215static const int JCV_DIRECTION_RIGHT = 1;
 
  216static const jcv_real JCV_INVALID_VALUE = (jcv_real)-JCV_FLT_MAX;
 
  220static inline jcv_real jcv_abs(jcv_real v)
 
  222  return (v < 0) ? -v : v;
 
  225static inline int jcv_real_eq(jcv_real a, jcv_real b)
 
  227  return jcv_abs(a - b) < JCV_REAL_TYPE_EPSILON;
 
  230static inline jcv_real jcv_real_to_int(jcv_real v)
 
  232  return (
sizeof(jcv_real) == 4) ? (jcv_real)(
int)v : (jcv_real)(
long long)v;
 
  236static inline jcv_real jcv_floor(jcv_real v)
 
  238  jcv_real i = jcv_real_to_int(v);
 
  239  return (v < i) ? i - 1 : i;
 
  243static inline jcv_real jcv_ceil(jcv_real v)
 
  245  jcv_real i = jcv_real_to_int(v);
 
  246  return (v > i) ? i + 1 : i;
 
  249static inline jcv_real jcv_min(jcv_real a, jcv_real b)
 
  251  return a < b ? a : b;
 
  254static inline jcv_real jcv_max(jcv_real a, jcv_real b)
 
  256  return a > b ? a : b;
 
  261static inline int jcv_point_cmp(
const void* p1, 
const void* p2)
 
  265  return (s1->y != s2->y) ? (s1->y < s2->y ? -1 : 1) : (s1->x < s2->x ? -1 : 1);
 
  270  return (pt1->y == pt2->y) ? (pt1->x < pt2->x) : pt1->y < pt2->y;
 
  275  return jcv_real_eq(pt1->y, pt2->y) && jcv_real_eq(pt1->x, pt2->x);
 
  280  return pt->x == min->x || pt->y == min->y || pt->x == max->x || pt->y == max->y;
 
  285static const int JCV_EDGE_LEFT = 1;
 
  286static const int JCV_EDGE_RIGHT = 2;
 
  287static const int JCV_EDGE_BOTTOM = 4;
 
  288static const int JCV_EDGE_TOP = 8;
 
  290static const int JCV_CORNER_NONE = 0;
 
  291static const int JCV_CORNER_TOP_LEFT = 1;
 
  292static const int JCV_CORNER_BOTTOM_LEFT = 2;
 
  293static const int JCV_CORNER_BOTTOM_RIGHT = 3;
 
  294static const int JCV_CORNER_TOP_RIGHT = 4;
 
  300    flags |= JCV_EDGE_LEFT;
 
  301  else if (pt->x == max->x)
 
  302    flags |= JCV_EDGE_RIGHT;
 
  304    flags |= JCV_EDGE_BOTTOM;
 
  305  else if (pt->y == max->y)
 
  306    flags |= JCV_EDGE_TOP;
 
  310static inline int jcv_edge_flags_to_corner(
int edge_flags)
 
  312#  define TEST_FLAGS(_FLAGS, _RETVAL) \ 
  313    if ((_FLAGS) == edge_flags)       \ 
  315  TEST_FLAGS(JCV_EDGE_TOP | JCV_EDGE_LEFT, JCV_CORNER_TOP_LEFT);
 
  316  TEST_FLAGS(JCV_EDGE_TOP | JCV_EDGE_RIGHT, JCV_CORNER_TOP_RIGHT);
 
  317  TEST_FLAGS(JCV_EDGE_BOTTOM | JCV_EDGE_LEFT, JCV_CORNER_BOTTOM_LEFT);
 
  318  TEST_FLAGS(JCV_EDGE_BOTTOM | JCV_EDGE_RIGHT, JCV_CORNER_BOTTOM_RIGHT);
 
  323static inline int jcv_is_corner(
int corner)
 
  328static inline int jcv_corner_rotate_90(
int corner)
 
  331  corner = (corner + 1) % 4;
 
  337  if (corner == JCV_CORNER_TOP_LEFT)
 
  342  else if (corner == JCV_CORNER_TOP_RIGHT)
 
  347  else if (corner == JCV_CORNER_BOTTOM_LEFT)
 
  352  else if (corner == JCV_CORNER_BOTTOM_RIGHT)
 
  359    p.x = JCV_INVALID_VALUE;
 
  360    p.y = JCV_INVALID_VALUE;
 
  367  jcv_real diffx = pt1->x - pt2->x;
 
  368  jcv_real diffy = pt1->y - pt2->y;
 
  369  return diffx * diffx + diffy * diffy;
 
  374  return (jcv_real)(JCV_SQRT(jcv_point_dist_sq(pt1, pt2)));
 
  379#  ifndef JCV_DISABLE_STRUCT_PACKING 
  380#    pragma pack(push, 1) 
  383typedef struct jcv_halfedge_
 
  386  struct jcv_halfedge_* left;
 
  387  struct jcv_halfedge_* right;
 
  394typedef struct jcv_memoryblock_
 
  397  struct jcv_memoryblock_* next;
 
  402typedef int (*FJCVPriorityQueuePrint)(
const void* node, 
int pos);
 
  404typedef struct jcv_priorityqueue_
 
  413struct jcv_context_internal_
 
  417  jcv_halfedge* beachline_start;
 
  418  jcv_halfedge* beachline_end;
 
  419  jcv_halfedge* last_inserted;
 
  420  jcv_priorityqueue* eventqueue;
 
  428  jcv_memoryblock* memblocks;
 
  430  jcv_halfedge* halfedgepool;
 
  441#  ifndef JCV_DISABLE_STRUCT_PACKING 
  447  jcv_context_internal* internal = d->internal;
 
  448  void* memctx = internal->memctx;
 
  449  FJCVFreeFn freefn = internal->free;
 
  450  while (internal->memblocks)
 
  452    jcv_memoryblock* p = internal->memblocks;
 
  453    internal->memblocks = internal->memblocks->next;
 
  457  freefn(memctx, internal->mem);
 
  462  return diagram->internal->sites;
 
  468  e.next = diagram->internal->edges;
 
  469  return jcv_diagram_get_next_edge(&e);
 
  475  while (e != 0 && jcv_point_eq(&
e->pos[0], &
e->pos[1]))
 
  485  iter->sentinel = jcv_diagram_get_edges(diagram);
 
  492    iter->current = iter->sentinel;
 
  501    iter->current = jcv_diagram_get_next_edge(iter->current);
 
  504  while (iter->current && (iter->current->sites[0] == 0 || iter->current->sites[1] == 0))
 
  506    iter->current = jcv_diagram_get_next_edge(iter->current);
 
  512  next->edge = iter->current;
 
  513  next->sites[0] = next->edge->sites[0];
 
  514  next->sites[1] = next->edge->sites[1];
 
  515  next->pos[0] = next->sites[0]->p;
 
  516  next->pos[1] = next->sites[1]->p;
 
  520static inline void* jcv_align(
void* value, 
size_t alignment)
 
  522  return (
void*)(((uintptr_t)value + (alignment - 1)) & ~(alignment - 1));
 
  525static void* jcv_alloc(jcv_context_internal* internal, 
size_t size)
 
  527  if (!internal->memblocks || internal->memblocks->sizefree < (size + 
sizeof(
void*)))
 
  529    size_t blocksize = 16 * 1024;
 
  530    jcv_memoryblock* block = (jcv_memoryblock*)internal->alloc(internal->memctx, blocksize);
 
  531    size_t offset = 
sizeof(jcv_memoryblock);
 
  532    block->sizefree = blocksize - offset;
 
  533    block->next = internal->memblocks;
 
  534    block->memory = ((
char*)block) + offset;
 
  535    internal->memblocks = block;
 
  537  void* p_raw = internal->memblocks->memory;
 
  538  void* p_aligned = jcv_align(p_raw, 
sizeof(
void*));
 
  539  size += (uintptr_t)p_aligned - (uintptr_t)p_raw;
 
  540  internal->memblocks->memory += size;
 
  541  internal->memblocks->sizefree -= size;
 
  545static jcv_edge* jcv_alloc_edge(jcv_context_internal* internal)
 
  550static jcv_halfedge* jcv_alloc_halfedge(jcv_context_internal* internal)
 
  552  if (internal->halfedgepool)
 
  554    jcv_halfedge* edge = internal->halfedgepool;
 
  555    internal->halfedgepool = internal->halfedgepool->right;
 
  559  return (jcv_halfedge*)jcv_alloc(internal, 
sizeof(jcv_halfedge));
 
  562static jcv_graphedge* jcv_alloc_graphedge(jcv_context_internal* internal)
 
  567static void* jcv_alloc_fn(
void* memctx, 
size_t size)
 
  573static void jcv_free_fn(
void* memctx, 
void* p)
 
  581static inline int jcv_is_valid(
const jcv_point* p)
 
  583  return (p->x != JCV_INVALID_VALUE || p->y != JCV_INVALID_VALUE) ? 1 : 0;
 
  591  e->pos[0].x = JCV_INVALID_VALUE;
 
  592  e->pos[0].y = JCV_INVALID_VALUE;
 
  593  e->pos[1].x = JCV_INVALID_VALUE;
 
  594  e->pos[1].y = JCV_INVALID_VALUE;
 
  611  jcv_real dx = s2->p.x - s1->p.x;
 
  612  jcv_real dy = s2->p.y - s1->p.y;
 
  613  int dx_is_larger = (dx * dx) > (dy * dy); 
 
  616  e->c = dx * (s1->p.x + dx * (jcv_real)0.5) + dy * (s1->p.y + dy * (jcv_real)0.5);
 
  635  return p.x >= clipper->min.x && p.x <= clipper->max.x &&
 
  636         p.y >= clipper->min.y && p.y <= clipper->max.y;
 
  643  jcv_real pxmin = clipper->min.x;
 
  644  jcv_real pxmax = clipper->max.x;
 
  645  jcv_real pymin = clipper->min.y;
 
  646  jcv_real pymax = clipper->max.y;
 
  648  jcv_real x1, y1, x2, y2;
 
  651  if (
e->a == (jcv_real)1 && 
e->b >= (jcv_real)0)
 
  653    s1 = jcv_is_valid(&
e->pos[1]) ? &
e->pos[1] : 0;
 
  654    s2 = jcv_is_valid(&
e->pos[0]) ? &
e->pos[0] : 0;
 
  658    s1 = jcv_is_valid(&
e->pos[0]) ? &
e->pos[0] : 0;
 
  659    s2 = jcv_is_valid(&
e->pos[1]) ? &
e->pos[1] : 0;
 
  662  if (
e->a == (jcv_real)1) 
 
  665    if (s1 != 0 && s1->y > pymin)
 
  673    x1 = 
e->c - 
e->b * y1;
 
  675    if (s2 != 0 && s2->y < pymax)
 
  682    x2 = (
e->c) - (
e->b) * y2;
 
  691      y1 = (
e->c - x1) / 
e->b;
 
  696      y1 = (
e->c - x1) / 
e->b;
 
  701      y2 = (
e->c - x2) / 
e->b;
 
  706      y2 = (
e->c - x2) / 
e->b;
 
  712    if (s1 != 0 && s1->x > pxmin)
 
  718    y1 = 
e->c - 
e->a * x1;
 
  720    if (s2 != 0 && s2->x < pxmax)
 
  726    y2 = 
e->c - 
e->a * x2;
 
  735      x1 = (
e->c - y1) / 
e->a;
 
  740      x1 = (
e->c - y1) / 
e->a;
 
  745      x2 = (
e->c - y2) / 
e->a;
 
  750      x2 = (
e->c - y2) / 
e->a;
 
  760  return (x1 == x2 && y1 == y2) ? 0 : 1;
 
  765static int jcv_edge_clipline(jcv_context_internal* internal, 
jcv_edge* e)
 
  767  return internal->clipper.clip_fn(&internal->clipper, e);
 
  773  jcv_edge_create(e, s1, s2);
 
  780static void jcv_halfedge_link(jcv_halfedge* edge, jcv_halfedge* newedge)
 
  782  newedge->left = edge;
 
  783  newedge->right = edge->right;
 
  784  edge->right->left = newedge;
 
  785  edge->right = newedge;
 
  788static inline void jcv_halfedge_unlink(jcv_halfedge* he)
 
  790  he->left->right = he->right;
 
  791  he->right->left = he->left;
 
  796static inline jcv_halfedge* jcv_halfedge_new(jcv_context_internal* internal, 
jcv_edge* e, 
int direction)
 
  798  jcv_halfedge* he = jcv_alloc_halfedge(internal);
 
  802  he->direction = direction;
 
  810static void jcv_halfedge_delete(jcv_context_internal* internal, jcv_halfedge* he)
 
  812  he->right = internal->halfedgepool;
 
  813  internal->halfedgepool = he;
 
  816static inline jcv_site* jcv_halfedge_leftsite(
const jcv_halfedge* he)
 
  818  return he->edge->sites[he->direction];
 
  821static inline jcv_site* jcv_halfedge_rightsite(
const jcv_halfedge* he)
 
  823  return he->edge ? he->edge->sites[1 - he->direction] : 0;
 
  826static int jcv_halfedge_rightof(
const jcv_halfedge* he, 
const jcv_point* p)
 
  831  int right_of_site = (p->x > topsite->p.x) ? 1 : 0;
 
  832  if (right_of_site && he->direction == JCV_DIRECTION_LEFT)
 
  834  if (!right_of_site && he->direction == JCV_DIRECTION_RIGHT)
 
  837  jcv_real dxp, dyp, dxs, t1, t2, t3, yl;
 
  840  if (
e->a == (jcv_real)1)
 
  842    dyp = p->y - topsite->p.y;
 
  843    dxp = p->x - topsite->p.x;
 
  845    if ((!right_of_site & (
e->b < (jcv_real)0)) | (right_of_site & (
e->b >= (jcv_real)0)))
 
  847      above = dyp >= 
e->b * dxp;
 
  852      above = (p->x + p->y * 
e->b) > 
e->c;
 
  853      if (
e->b < (jcv_real)0)
 
  860      dxs = topsite->p.x - 
e->sites[0]->p.x;
 
  861      above = 
e->b * (dxp * dxp - dyp * dyp) < dxs * dyp * ((jcv_real)1 + (jcv_real)2 * dxp / dxs + 
e->b * 
e->b);
 
  862      if (
e->b < (jcv_real)0)
 
  868    yl = 
e->c - 
e->a * p->x;
 
  870    t2 = p->x - topsite->p.x;
 
  871    t3 = yl - topsite->p.y;
 
  872    above = t1 * t1 > (t2 * t2 + t3 * t3);
 
  874  return (he->direction == JCV_DIRECTION_LEFT ? above : !above);
 
  879static inline int jcv_halfedge_compare(
const jcv_halfedge* he1, 
const jcv_halfedge* he2)
 
  881  return (he1->y == he2->y) ? he1->vertex.x > he2->vertex.x : he1->y > he2->y;
 
  884static int jcv_halfedge_intersect(
const jcv_halfedge* he1, 
const jcv_halfedge* he2, 
jcv_point* out)
 
  889  jcv_real d = e1->a * e2->b - e1->b * e2->a;
 
  890  if (((jcv_real)-JCV_EDGE_INTERSECT_THRESHOLD < d && d < (jcv_real)JCV_EDGE_INTERSECT_THRESHOLD))
 
  894  out->x = (e1->c * e2->b - e1->b * e2->c) / d;
 
  895  out->y = (e1->a * e2->c - e1->c * e2->a) / d;
 
  898  const jcv_halfedge* he;
 
  899  if (jcv_point_less(&e1->sites[1]->p, &e2->sites[1]->p))
 
  910  int right_of_site = out->x >= 
e->sites[1]->p.x;
 
  911  if ((right_of_site && he->direction == JCV_DIRECTION_LEFT) || (!right_of_site && he->direction == JCV_DIRECTION_RIGHT))
 
  922static int jcv_pq_moveup(jcv_priorityqueue* pq, 
int pos)
 
  924  jcv_halfedge** items = (jcv_halfedge**)pq->items;
 
  925  jcv_halfedge* node = items[pos];
 
  927  for (
int parent = (pos >> 1);
 
  928       pos > 1 && jcv_halfedge_compare(items[parent], node);
 
  929       pos = parent, parent = parent >> 1)
 
  931    items[pos] = items[parent];
 
  932    items[pos]->pqpos = pos;
 
  940static int jcv_pq_maxchild(jcv_priorityqueue* pq, 
int pos)
 
  942  int child = pos << 1;
 
  943  if (child >= pq->numitems)
 
  945  jcv_halfedge** items = (jcv_halfedge**)pq->items;
 
  946  if ((child + 1) < pq->numitems && jcv_halfedge_compare(items[child], items[child + 1]))
 
  951static int jcv_pq_movedown(jcv_priorityqueue* pq, 
int pos)
 
  953  jcv_halfedge** items = (jcv_halfedge**)pq->items;
 
  954  jcv_halfedge* node = items[pos];
 
  956  int child = jcv_pq_maxchild(pq, pos);
 
  957  while (child && jcv_halfedge_compare(node, items[child]))
 
  959    items[pos] = items[child];
 
  960    items[pos]->pqpos = pos;
 
  962    child = jcv_pq_maxchild(pq, pos);
 
  966  items[pos]->pqpos = pos;
 
  970static void jcv_pq_create(jcv_priorityqueue* pq, 
int capacity, 
void** buffer)
 
  972  pq->maxnumitems = capacity;
 
  977static int jcv_pq_empty(jcv_priorityqueue* pq)
 
  979  return pq->numitems == 1 ? 1 : 0;
 
  982static int jcv_pq_push(jcv_priorityqueue* pq, 
void* node)
 
  984  assert(pq->numitems < pq->maxnumitems);
 
  985  int n = pq->numitems++;
 
  987  return jcv_pq_moveup(pq, n);
 
  990static void* jcv_pq_pop(jcv_priorityqueue* pq)
 
  992  void* node = pq->items[1];
 
  993  pq->items[1] = pq->items[--pq->numitems];
 
  994  jcv_pq_movedown(pq, 1);
 
  998static void* jcv_pq_top(jcv_priorityqueue* pq)
 
 1000  return pq->items[1];
 
 1003static void jcv_pq_remove(jcv_priorityqueue* pq, jcv_halfedge* node)
 
 1005  if (pq->numitems == 1)
 
 1007  int pos = node->pqpos;
 
 1011  jcv_halfedge** items = (jcv_halfedge**)pq->items;
 
 1013  items[pos] = items[--pq->numitems];
 
 1014  if (jcv_halfedge_compare(node, items[pos]))
 
 1015    jcv_pq_moveup(pq, pos);
 
 1017    jcv_pq_movedown(pq, pos);
 
 1023static inline jcv_site* jcv_nextsite(jcv_context_internal* internal)
 
 1025  return (internal->currentsite < internal->numsites) ? &internal->sites[internal->currentsite++] : 0;
 
 1028static jcv_halfedge* jcv_get_edge_above_x(jcv_context_internal* internal, 
const jcv_point* p)
 
 1033  jcv_halfedge* he = internal->last_inserted;
 
 1036    if (p->x < (internal->rect.max.x - internal->rect.min.x) / 2)
 
 1037      he = internal->beachline_start;
 
 1039      he = internal->beachline_end;
 
 1043  if (he == internal->beachline_start || (he != internal->beachline_end && jcv_halfedge_rightof(he, p)))
 
 1048    } 
while (he != internal->beachline_end && jcv_halfedge_rightof(he, p));
 
 1057    } 
while (he != internal->beachline_start && !jcv_halfedge_rightof(he, p));
 
 1063static int jcv_check_circle_event(
const jcv_halfedge* he1, 
const jcv_halfedge* he2, 
jcv_point* vertex)
 
 1067  if (e1 == 0 || e2 == 0 || e1->sites[1] == e2->sites[1])
 
 1072  return jcv_halfedge_intersect(he1, he2, vertex);
 
 1075static void jcv_site_event(jcv_context_internal* internal, 
jcv_site* site)
 
 1077  jcv_halfedge* left = jcv_get_edge_above_x(internal, &site->p);
 
 1078  jcv_halfedge* right = left->right;
 
 1079  jcv_site* bottom = jcv_halfedge_rightsite(left);
 
 1081    bottom = internal->bottomsite;
 
 1083  jcv_edge* edge = jcv_edge_new(internal, bottom, site);
 
 1084  edge->next = internal->edges;
 
 1085  internal->edges = edge;
 
 1087  jcv_halfedge* edge1 = jcv_halfedge_new(internal, edge, JCV_DIRECTION_LEFT);
 
 1088  jcv_halfedge* edge2 = jcv_halfedge_new(internal, edge, JCV_DIRECTION_RIGHT);
 
 1090  jcv_halfedge_link(left, edge1);
 
 1091  jcv_halfedge_link(edge1, edge2);
 
 1093  internal->last_inserted = right;
 
 1096  if (jcv_check_circle_event(left, edge1, &p))
 
 1098    jcv_pq_remove(internal->eventqueue, left);
 
 1100    left->y = p.y + jcv_point_dist(&site->p, &p);
 
 1101    jcv_pq_push(internal->eventqueue, left);
 
 1103  if (jcv_check_circle_event(edge2, right, &p))
 
 1106    edge2->y = p.y + jcv_point_dist(&site->p, &p);
 
 1107    jcv_pq_push(internal->eventqueue, edge2);
 
 1114  return (b->x - a->x) * (c->y - a->y) - (b->y - a->y) * (c->x - a->x);
 
 1120  jcv_real half = 1 / (jcv_real)2;
 
 1121  jcv_real x = (edge->pos[0].x + edge->pos[1].x) * half;
 
 1122  jcv_real y = (edge->pos[0].y + edge->pos[1].y) * half;
 
 1123  jcv_real diffy = y - site->p.y;
 
 1124  jcv_real angle = JCV_ATAN2(diffy, x - site->p.x);
 
 1126    angle = angle + 2 * JCV_PI;
 
 1127  return (jcv_real)angle;
 
 1132  return jcv_real_eq(a->angle, b->angle) && jcv_point_eq(&a->pos[0], &b->pos[0]) && jcv_point_eq(&a->pos[1], &b->pos[1]);
 
 1139  if (site->edges == 0 || site->edges->angle >= edge->angle)
 
 1141    edge->next = site->edges;
 
 1148    while (current->next != 0 && current->next->angle < edge->angle)
 
 1150      current = current->next;
 
 1153    edge->next = current->next;
 
 1154    current->next = edge;
 
 1158  if (prev && jcv_graphedge_eq(prev, edge))
 
 1160    prev->next = edge->next;
 
 1162  else if (edge->next && jcv_graphedge_eq(edge, edge->next))
 
 1164    edge->next = edge->next->next;
 
 1168static void jcv_finishline(jcv_context_internal* internal, 
jcv_edge* e)
 
 1170  if (!jcv_edge_clipline(internal, e))
 
 1176  int flip = jcv_determinant(&
e->sites[0]->p, &
e->pos[0], &
e->pos[1]) > (jcv_real)0 ? 0 : 1;
 
 1178  for (
int i = 0; i < 2; ++i)
 
 1184    ge->neighbor = 
e->sites[1 - i];
 
 1185    ge->pos[flip] = 
e->pos[i];
 
 1186    ge->pos[1 - flip] = 
e->pos[1 - i];
 
 1187    ge->angle = jcv_calc_sort_metric(
e->sites[i], ge);
 
 1189    jcv_sortedges_insert(
e->sites[i], ge);
 
 1194static void jcv_endpos(jcv_context_internal* internal, 
jcv_edge* e, 
const jcv_point* p, 
int direction)
 
 1196  e->pos[direction] = *p;
 
 1198  if (!jcv_is_valid(&
e->pos[1 - direction]))
 
 1201  jcv_finishline(internal, e);
 
 1207  gap->pos[0] = current->pos[1];
 
 1209  if (current->pos[1].x < internal->rect.max.x && current->pos[1].y == internal->rect.min.y)
 
 1211    gap->pos[1].x = internal->rect.max.x;
 
 1212    gap->pos[1].y = internal->rect.min.y;
 
 1214  else if (current->pos[1].x > internal->rect.min.x && current->pos[1].y == internal->rect.max.y)
 
 1216    gap->pos[1].x = internal->rect.min.x;
 
 1217    gap->pos[1].y = internal->rect.max.y;
 
 1219  else if (current->pos[1].y > internal->rect.min.y && current->pos[1].x == internal->rect.min.x)
 
 1221    gap->pos[1].x = internal->rect.min.x;
 
 1222    gap->pos[1].y = internal->rect.min.y;
 
 1224  else if (current->pos[1].y < internal->rect.max.y && current->pos[1].x == internal->rect.max.x)
 
 1226    gap->pos[1].x = internal->rect.max.x;
 
 1227    gap->pos[1].y = internal->rect.max.y;
 
 1230  gap->angle = jcv_calc_sort_metric(site, gap);
 
 1235  jcv_edge* edge = jcv_alloc_edge(internal);
 
 1236  edge->pos[0] = ge->pos[0];
 
 1237  edge->pos[1] = ge->pos[1];
 
 1238  edge->sites[0] = site;
 
 1240  edge->a = edge->b = edge->c = 0;
 
 1241  edge->next = internal->edges;
 
 1242  internal->edges = edge;
 
 1246void jcv_boxshape_fillgaps(
const jcv_clipper* clipper, jcv_context_internal* allocator, 
jcv_site* site)
 
 1253    assert(allocator->numsites == 1);
 
 1257    gap->pos[0] = clipper->min;
 
 1258    gap->pos[1].x = clipper->max.x;
 
 1259    gap->pos[1].y = clipper->min.y;
 
 1260    gap->angle = jcv_calc_sort_metric(site, gap);
 
 1262    gap->edge = jcv_create_gap_edge(allocator, site, gap);
 
 1272    jcv_create_corner_edge(allocator, site, current, gap);
 
 1273    gap->edge = jcv_create_gap_edge(allocator, site, gap);
 
 1275    gap->next = current->next;
 
 1276    current->next = gap;
 
 1281  while (current && next)
 
 1283    int current_edge_flags = jcv_get_edge_flags(¤t->pos[1], &clipper->min, &clipper->max);
 
 1284    if (current_edge_flags && !jcv_point_eq(¤t->pos[1], &next->pos[0]))
 
 1292      int next_edge_flags = jcv_get_edge_flags(&next->pos[0], &clipper->min, &clipper->max);
 
 1293      if (current_edge_flags & next_edge_flags)
 
 1298        gap->pos[0] = current->pos[1];
 
 1299        gap->pos[1] = next->pos[0];
 
 1300        gap->angle = jcv_calc_sort_metric(site, gap);
 
 1301        gap->edge = jcv_create_gap_edge(allocator, site, gap);
 
 1303        gap->next = current->next;
 
 1304        current->next = gap;
 
 1309        int corner_flag = jcv_edge_flags_to_corner(current_edge_flags);
 
 1313          corner_flag = jcv_corner_rotate_90(corner_flag);
 
 1319          if (current_edge_flags == JCV_EDGE_TOP)
 
 1321            corner_flag = JCV_CORNER_TOP_LEFT;
 
 1323          else if (current_edge_flags == JCV_EDGE_LEFT)
 
 1325            corner_flag = JCV_CORNER_BOTTOM_LEFT;
 
 1327          else if (current_edge_flags == JCV_EDGE_BOTTOM)
 
 1329            corner_flag = JCV_CORNER_BOTTOM_RIGHT;
 
 1331          else if (current_edge_flags == JCV_EDGE_RIGHT)
 
 1333            corner_flag = JCV_CORNER_TOP_RIGHT;
 
 1336        jcv_point corner = jcv_corner_to_point(corner_flag, &clipper->min, &clipper->max);
 
 1340        gap->pos[0] = current->pos[1];
 
 1341        gap->pos[1] = corner;
 
 1342        gap->angle = jcv_calc_sort_metric(site, gap);
 
 1343        gap->edge = jcv_create_gap_edge(allocator, site, gap);
 
 1345        gap->next = current->next;
 
 1346        current->next = gap;
 
 1350    current = current->next;
 
 1353      next = current->next;
 
 1364  jcv_context_internal* internal = diagram->internal;
 
 1365  if (!internal->clipper.fill_fn)
 
 1368  for (
int i = 0; i < internal->numsites; ++i)
 
 1370    jcv_site* site = &internal->sites[i];
 
 1371    internal->clipper.fill_fn(&internal->clipper, internal, site);
 
 1376static void jcv_circle_event(jcv_context_internal* internal)
 
 1378  jcv_halfedge* left = (jcv_halfedge*)jcv_pq_pop(internal->eventqueue);
 
 1380  jcv_halfedge* leftleft = left->left;
 
 1381  jcv_halfedge* right = left->right;
 
 1382  jcv_halfedge* rightright = right->right;
 
 1383  jcv_site* bottom = jcv_halfedge_leftsite(left);
 
 1384  jcv_site* top = jcv_halfedge_rightsite(right);
 
 1387  jcv_endpos(internal, left->edge, &vertex, left->direction);
 
 1388  jcv_endpos(internal, right->edge, &vertex, right->direction);
 
 1390  internal->last_inserted = rightright;
 
 1392  jcv_pq_remove(internal->eventqueue, right);
 
 1393  jcv_halfedge_unlink(left);
 
 1394  jcv_halfedge_unlink(right);
 
 1395  jcv_halfedge_delete(internal, left);
 
 1396  jcv_halfedge_delete(internal, right);
 
 1398  int direction = JCV_DIRECTION_LEFT;
 
 1399  if (bottom->p.y > top->p.y)
 
 1404    direction = JCV_DIRECTION_RIGHT;
 
 1407  jcv_edge* edge = jcv_edge_new(internal, bottom, top);
 
 1408  edge->next = internal->edges;
 
 1409  internal->edges = edge;
 
 1411  jcv_halfedge* he = jcv_halfedge_new(internal, edge, direction);
 
 1412  jcv_halfedge_link(leftleft, he);
 
 1413  jcv_endpos(internal, edge, &vertex, JCV_DIRECTION_RIGHT - direction);
 
 1416  if (jcv_check_circle_event(leftleft, he, &p))
 
 1418    jcv_pq_remove(internal->eventqueue, leftleft);
 
 1419    leftleft->vertex = p;
 
 1420    leftleft->y = p.y + jcv_point_dist(&bottom->p, &p);
 
 1421    jcv_pq_push(internal->eventqueue, leftleft);
 
 1423  if (jcv_check_circle_event(he, rightright, &p))
 
 1426    he->y = p.y + jcv_point_dist(&bottom->p, &p);
 
 1427    jcv_pq_push(internal->eventqueue, he);
 
 1433  jcv_diagram_generate_useralloc(num_points, points, rect, clipper, 0, jcv_alloc_fn, jcv_free_fn, d);
 
 1436typedef union jcv_cast_align_struct_
 
 1440} jcv_cast_align_struct;
 
 1444  rect->min.x = jcv_min(rect->min.x, p->x);
 
 1445  rect->min.y = jcv_min(rect->min.y, p->y);
 
 1446  rect->max.x = jcv_max(rect->max.x, p->x);
 
 1447  rect->max.y = jcv_max(rect->max.y, p->y);
 
 1450static inline void jcv_rect_round(
jcv_rect* rect)
 
 1452  rect->min.x = jcv_floor(rect->min.x);
 
 1453  rect->min.y = jcv_floor(rect->min.y);
 
 1454  rect->max.x = jcv_ceil(rect->max.x);
 
 1455  rect->max.y = jcv_ceil(rect->max.y);
 
 1458static inline void jcv_rect_inflate(
jcv_rect* rect, jcv_real amount)
 
 1460  rect->min.x -= amount;
 
 1461  rect->min.y -= amount;
 
 1462  rect->max.x += amount;
 
 1463  rect->max.y += amount;
 
 1466static int jcv_prune_duplicates(jcv_context_internal* internal, 
jcv_rect* rect)
 
 1468  int num_sites = internal->numsites;
 
 1472  r.min.x = r.min.y = JCV_FLT_MAX;
 
 1473  r.max.x = r.max.y = -JCV_FLT_MAX;
 
 1477  for (
int i = 0; i < num_sites; i++)
 
 1481    if (i > 0 && jcv_point_eq(&s->p, &sites[i - 1].p))
 
 1487    sites[i - offset] = sites[i];
 
 1489    jcv_rect_union(&r, &s->p);
 
 1491  internal->numsites -= offset;
 
 1499static int jcv_prune_not_in_shape(jcv_context_internal* internal, 
jcv_rect* rect)
 
 1501  int num_sites = internal->numsites;
 
 1505  r.min.x = r.min.y = JCV_FLT_MAX;
 
 1506  r.max.x = r.max.y = -JCV_FLT_MAX;
 
 1509  for (
int i = 0; i < num_sites; i++)
 
 1513    if (!internal->clipper.test_fn(&internal->clipper, s->p))
 
 1519    sites[i - offset] = sites[i];
 
 1521    jcv_rect_union(&r, &s->p);
 
 1523  internal->numsites -= offset;
 
 1531static jcv_context_internal* jcv_alloc_internal(
int num_points, 
void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn)
 
 1536  size_t eventssize = (size_t)(num_points * 2) * 
sizeof(
void*);                                             
 
 1537  size_t sitessize = (size_t)num_points * 
sizeof(
jcv_site);
 
 1538  size_t memsize = 
sizeof(jcv_priorityqueue) + eventssize + sitessize + 
sizeof(jcv_context_internal) + 16u; 
 
 1540  char* originalmem = (
char*)allocfn(userallocctx, memsize);
 
 1541  memset(originalmem, 0, memsize);
 
 1544  char* mem = (
char*)jcv_align(originalmem, 
sizeof(
void*));
 
 1546  jcv_context_internal* internal = (jcv_context_internal*)mem;
 
 1547  mem += 
sizeof(jcv_context_internal);
 
 1548  internal->mem = originalmem;
 
 1549  internal->memctx = userallocctx;
 
 1550  internal->alloc = allocfn;
 
 1551  internal->free = freefn;
 
 1553  mem = (
char*)jcv_align(mem, 
sizeof(
void*));
 
 1557  mem = (
char*)jcv_align(mem, 
sizeof(
void*));
 
 1558  internal->eventqueue = (jcv_priorityqueue*)mem;
 
 1559  mem += 
sizeof(jcv_priorityqueue);
 
 1560  assert(((uintptr_t)mem & (
sizeof(
void*) - 1)) == 0);
 
 1562  jcv_cast_align_struct tmp;
 
 1564  internal->eventmem = tmp.voidpp;
 
 1566  assert((mem + eventssize) <= (originalmem + memsize));
 
 1571void jcv_diagram_generate_useralloc(
int num_points, 
const jcv_point* points, 
const jcv_rect* rect, 
const jcv_clipper* clipper, 
void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, 
jcv_diagram* d)
 
 1574    jcv_diagram_free(d);
 
 1576  jcv_context_internal* internal = jcv_alloc_internal(num_points, userallocctx, allocfn, freefn);
 
 1578  internal->beachline_start = jcv_halfedge_new(internal, 0, 0);
 
 1579  internal->beachline_end = jcv_halfedge_new(internal, 0, 0);
 
 1581  internal->beachline_start->left = 0;
 
 1582  internal->beachline_start->right = internal->beachline_end;
 
 1583  internal->beachline_end->left = internal->beachline_start;
 
 1584  internal->beachline_end->right = 0;
 
 1586  internal->last_inserted = 0;
 
 1588  int max_num_events = num_points * 2; 
 
 1589  jcv_pq_create(internal->eventqueue, max_num_events, (
void**)internal->eventmem);
 
 1591  internal->numsites = num_points;
 
 1594  for (
int i = 0; i < num_points; ++i)
 
 1596    sites[i].p = points[i];
 
 1601  qsort(sites, (
size_t)num_points, 
sizeof(
jcv_site), jcv_point_cmp);
 
 1606    box_clipper.test_fn = jcv_boxshape_test;
 
 1607    box_clipper.clip_fn = jcv_boxshape_clip;
 
 1608    box_clipper.fill_fn = jcv_boxshape_fillgaps;
 
 1609    clipper = &box_clipper;
 
 1611  internal->clipper = *clipper;
 
 1614  tmp_rect.min.x = tmp_rect.min.y = JCV_FLT_MAX;
 
 1615  tmp_rect.max.x = tmp_rect.max.y = -JCV_FLT_MAX;
 
 1616  jcv_prune_duplicates(internal, &tmp_rect);
 
 1619  if (internal->clipper.test_fn)
 
 1622    internal->clipper.min = rect ? rect->min : tmp_rect.min;
 
 1623    internal->clipper.max = rect ? rect->max : tmp_rect.max;
 
 1625    jcv_prune_not_in_shape(internal, &tmp_rect);
 
 1632      jcv_rect_round(&tmp_rect);
 
 1633      jcv_rect_inflate(&tmp_rect, 10);
 
 1635      internal->clipper.min = tmp_rect.min;
 
 1636      internal->clipper.max = tmp_rect.max;
 
 1640  internal->rect = rect ? *rect : tmp_rect;
 
 1642  d->min = internal->rect.min;
 
 1643  d->max = internal->rect.max;
 
 1644  d->numsites = internal->numsites;
 
 1645  d->internal = internal;
 
 1647  internal->bottomsite = jcv_nextsite(internal);
 
 1649  jcv_priorityqueue* pq = internal->eventqueue;
 
 1650  jcv_site* site = jcv_nextsite(internal);
 
 1656    if (!jcv_pq_empty(pq))
 
 1658      jcv_halfedge* he = (jcv_halfedge*)jcv_pq_top(pq);
 
 1659      lowest_pq_point.x = he->vertex.x;
 
 1660      lowest_pq_point.y = he->y;
 
 1663    if (site != 0 && (jcv_pq_empty(pq) || jcv_point_less(&site->p, &lowest_pq_point)))
 
 1665      jcv_site_event(internal, site);
 
 1666      site = jcv_nextsite(internal);
 
 1668    else if (!jcv_pq_empty(pq))
 
 1670      jcv_circle_event(internal);
 
 1678  for (jcv_halfedge* he = internal->beachline_start->right; he != internal->beachline_end; he = he->right)
 
 1680    jcv_finishline(internal, he->edge);
 
constexpr TYPE e()
Returns the natural constant e.
Definition jc_voronoi.h:176
Definition jc_voronoi.h:163
Definition jc_voronoi.h:157
Definition jc_voronoi.h:186
Definition jc_voronoi.h:147
Definition jc_voronoi.h:130
Definition jc_voronoi.h:124
Definition jc_voronoi.h:170
Definition jc_voronoi.h:139