PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ _lwt_AddPoint()

static LWT_ELEMID _lwt_AddPoint ( LWT_TOPOLOGY topo,
LWPOINT point,
double  tol,
int  findFace,
int *  moved 
)
static

Definition at line 6752 of file lwgeom_topo.c.

6754 {
6755  uint64_t num, i;
6756  double mindist = FLT_MAX;
6757  LWT_ISO_NODE *nodes, *nodes2;
6758  LWT_ISO_EDGE *edges;
6759  LWGEOM *pt = lwpoint_as_lwgeom(point);
6760  scored_pointer *sorted;
6761  int flds;
6762  LWT_ELEMID id = 0;
6763 
6764  /* Get tolerance, if 0 was given */
6765  if (!tol)
6766  tol = _LWT_MINTOLERANCE(topo, pt);
6767 
6768  LWDEBUGG(1, pt, "Adding point");
6769 
6770  /*
6771  -- 1. Check if any existing node is closer than the given precision
6772  -- and if so pick the closest
6773  TODO: use WithinBox2D
6774  */
6776  nodes = lwt_be_getNodeWithinDistance2D(topo, point, tol, &num, flds, 0);
6777  if (num == UINT64_MAX)
6778  {
6779  PGTOPO_BE_ERROR();
6780  return -1;
6781  }
6782  if ( num )
6783  {
6784  LWDEBUGF(1, "New point is within %.15g units of %llu nodes", tol, num);
6785  /* Order by distance if there are more than a single return */
6786  if ( num > 1 )
6787  {{
6788  sorted = lwalloc(sizeof(scored_pointer)*num);
6789  for (i=0; i<num; ++i)
6790  {
6791  sorted[i].ptr = nodes+i;
6792  sorted[i].score = lwgeom_mindistance2d(lwpoint_as_lwgeom(nodes[i].geom), pt);
6793  LWDEBUGF(1, "Node %" LWTFMT_ELEMID " distance: %.15g",
6794  ((LWT_ISO_NODE*)(sorted[i].ptr))->node_id, sorted[i].score);
6795  }
6796  qsort(sorted, num, sizeof(scored_pointer), compare_scored_pointer);
6797  nodes2 = lwalloc(sizeof(LWT_ISO_NODE)*num);
6798  for (i=0; i<num; ++i)
6799  {
6800  nodes2[i] = *((LWT_ISO_NODE*)sorted[i].ptr);
6801  }
6802  lwfree(sorted);
6803  lwfree(nodes);
6804  nodes = nodes2;
6805  }}
6806 
6807  for ( i=0; i<num; ++i )
6808  {
6809  LWT_ISO_NODE *n = &(nodes[i]);
6810  LWGEOM *g = lwpoint_as_lwgeom(n->geom);
6811  double dist = lwgeom_mindistance2d(g, pt);
6812  /* TODO: move this check in the previous sort scan ... */
6813  /* must be closer than tolerated, unless distance is zero */
6814  if ( dist && dist >= tol ) continue;
6815  if ( ! id || dist < mindist )
6816  {
6817  id = n->node_id;
6818  mindist = dist;
6819  }
6820  }
6821  if ( id )
6822  {
6823  /* found an existing node */
6824  if ( nodes ) _lwt_release_nodes(nodes, num);
6825  if ( moved ) *moved = mindist == 0 ? 0 : 1;
6826  return id;
6827  }
6828  }
6829 
6830  initGEOS(lwnotice, lwgeom_geos_error);
6831 
6832  /*
6833  -- 2. Check if any existing edge falls within tolerance
6834  -- and if so split it by a point projected on it
6835  TODO: use WithinBox2D
6836  */
6837  flds = LWT_COL_EDGE_ALL; /* EDGE_ID|LWT_COL_EDGE_GEOM;*/
6838  edges = lwt_be_getEdgeWithinDistance2D(topo, point, tol, &num, flds, 0);
6839  if (num == UINT64_MAX)
6840  {
6841  PGTOPO_BE_ERROR();
6842  return -1;
6843  }
6844  LWDEBUGF(1, "New point is within %.15g units of %llu edges", tol, num);
6845  if ( num )
6846  {
6847  id = _lwt_SplitAllEdgesToNewNode(topo, edges, num, lwgeom_as_lwpoint(pt), tol, moved);
6848  _lwt_release_edges(edges, num);
6849  }
6850 
6851  if ( id == 0 )
6852  {
6853  /* The point is isolated, add it as such */
6854  /* TODO: pass 1 as last argument (skipChecks) ? */
6855  id = _lwt_AddIsoNode(topo, -1, point, 0, findFace);
6856  if ( moved ) *moved = 0;
6857  if ( -1 == id )
6858  {
6859  /* should have invoked lwerror already, leaking memory */
6860  _lwt_release_edges(edges, num);
6861  lwerror("lwt_AddIsoNode failed");
6862  return -1;
6863  }
6864  }
6865 
6866  return id;
6867 }
void lwgeom_geos_error(const char *fmt,...)
void lwfree(void *mem)
Definition: lwutil.c:248
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:344
double lwgeom_mindistance2d(const LWGEOM *lw1, const LWGEOM *lw2)
Function initializing min distance calculation.
Definition: measures.c:200
void * lwalloc(size_t size)
Definition: lwutil.c:227
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_EDGE_ALL
#define LWT_COL_NODE_GEOM
#define LWT_COL_NODE_NODE_ID
Node fields.
#define PGTOPO_BE_ERROR()
#define LWTFMT_ELEMID
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:106
void lwnotice(const char *fmt,...) __attribute__((format(printf
Write a notice out to the notice handler.
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
#define LWDEBUGG(level, geom, msg)
Definition: lwgeom_log.h:111
static LWT_ELEMID _lwt_AddIsoNode(LWT_TOPOLOGY *topo, LWT_ELEMID face, LWPOINT *pt, int skipISOChecks, int checkFace)
Definition: lwgeom_topo.c:526
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
Definition: lwgeom_topo.c:470
static int compare_scored_pointer(const void *si1, const void *si2)
Definition: lwgeom_topo.c:5071
void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
Definition: lwgeom_topo.c:460
LWT_ISO_NODE * lwt_be_getNodeWithinDistance2D(LWT_TOPOLOGY *topo, const LWPOINT *pt, double dist, uint64_t *numelems, int fields, int64_t limit)
Definition: lwgeom_topo.c:156
#define _LWT_MINTOLERANCE(topo, geom)
Definition: lwgeom_topo.c:5062
static LWT_ELEMID _lwt_SplitAllEdgesToNewNode(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edges, uint64_t num, LWPOINT *point, double tol, int *moved)
Definition: lwgeom_topo.c:6515
LWT_ISO_EDGE * lwt_be_getEdgeWithinDistance2D(LWT_TOPOLOGY *topo, const LWPOINT *pt, double dist, uint64_t *numelems, int fields, int64_t limit)
Definition: lwgeom_topo.c:245
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition: lwinline.h:127
LWT_ELEMID node_id
LWPOINT * geom

References _lwt_AddIsoNode(), _LWT_MINTOLERANCE, _lwt_release_edges(), _lwt_release_nodes(), _lwt_SplitAllEdgesToNewNode(), compare_scored_pointer(), LWT_ISO_NODE::geom, lwalloc(), LWDEBUGF, LWDEBUGG, lwerror(), lwfree(), lwgeom_as_lwpoint(), lwgeom_geos_error(), lwgeom_mindistance2d(), lwnotice(), lwpoint_as_lwgeom(), lwt_be_getEdgeWithinDistance2D(), lwt_be_getNodeWithinDistance2D(), LWT_COL_EDGE_ALL, LWT_COL_NODE_GEOM, LWT_COL_NODE_NODE_ID, LWTFMT_ELEMID, LWT_ISO_NODE::node_id, PGTOPO_BE_ERROR, scored_pointer_t::ptr, and scored_pointer_t::score.

Referenced by _lwt_AddLineEdge(), lwt_AddPoint(), and lwt_LoadPoint().

Here is the call graph for this function:
Here is the caller graph for this function: