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,
int *  numSplitEdges 
)
static

Definition at line 6754 of file lwgeom_topo.c.

6756 {
6757  uint64_t num, i;
6758  double mindist = FLT_MAX;
6759  LWT_ISO_NODE *nodes, *nodes2;
6760  LWT_ISO_EDGE *edges;
6761  LWGEOM *pt = lwpoint_as_lwgeom(point);
6762  scored_pointer *sorted;
6763  int flds;
6764  LWT_ELEMID id = 0;
6765 
6766  /* Get tolerance, if 0 was given */
6767  if ( tol == -1 )
6768  tol = _LWT_MINTOLERANCE(topo, pt);
6769 
6770  LWDEBUGG(1, pt, "Adding point");
6771 
6772  /*
6773  -- 1. Check if any existing node is closer than the given precision
6774  -- and if so pick the closest
6775  TODO: use WithinBox2D
6776  */
6778  nodes = lwt_be_getNodeWithinDistance2D(topo, point, tol, &num, flds, 0);
6779  if (num == UINT64_MAX)
6780  {
6781  PGTOPO_BE_ERROR();
6782  return -1;
6783  }
6784 
6785  if ( numSplitEdges ) *numSplitEdges = 0;
6786 
6787  if ( num )
6788  {
6789  LWDEBUGF(1, "New point is within %.15g units of %llu nodes", tol, num);
6790  /* Order by distance if there are more than a single return */
6791  if ( num > 1 )
6792  {{
6793  sorted = lwalloc(sizeof(scored_pointer)*num);
6794  for (i=0; i<num; ++i)
6795  {
6796  sorted[i].ptr = nodes+i;
6797  sorted[i].score = lwgeom_mindistance2d(lwpoint_as_lwgeom(nodes[i].geom), pt);
6798  LWDEBUGF(1, "Node %" LWTFMT_ELEMID " distance: %.15g",
6799  ((LWT_ISO_NODE*)(sorted[i].ptr))->node_id, sorted[i].score);
6800  }
6801  qsort(sorted, num, sizeof(scored_pointer), compare_scored_pointer);
6802  nodes2 = lwalloc(sizeof(LWT_ISO_NODE)*num);
6803  for (i=0; i<num; ++i)
6804  {
6805  nodes2[i] = *((LWT_ISO_NODE*)sorted[i].ptr);
6806  }
6807  lwfree(sorted);
6808  lwfree(nodes);
6809  nodes = nodes2;
6810  }}
6811 
6812  for ( i=0; i<num; ++i )
6813  {
6814  LWT_ISO_NODE *n = &(nodes[i]);
6815  LWGEOM *g = lwpoint_as_lwgeom(n->geom);
6816  double dist = lwgeom_mindistance2d(g, pt);
6817  /* TODO: move this check in the previous sort scan ... */
6818  /* must be closer than tolerated, unless distance is zero */
6819  if ( dist && dist >= tol ) continue;
6820  if ( ! id || dist < mindist )
6821  {
6822  id = n->node_id;
6823  mindist = dist;
6824  }
6825  }
6826  if ( id )
6827  {
6828  /* found an existing node */
6829  if ( nodes ) _lwt_release_nodes(nodes, num);
6830  if ( moved ) *moved = mindist == 0 ? 0 : 1;
6831  return id;
6832  }
6833  }
6834 
6835  initGEOS(lwnotice, lwgeom_geos_error);
6836 
6837  /*
6838  -- 2. Check if any existing edge falls within tolerance
6839  -- and if so split it by a point projected on it
6840  TODO: use WithinBox2D
6841  */
6842  flds = LWT_COL_EDGE_ALL; /* EDGE_ID|LWT_COL_EDGE_GEOM;*/
6843  edges = lwt_be_getEdgeWithinDistance2D(topo, point, tol, &num, flds, 0);
6844  if (num == UINT64_MAX)
6845  {
6846  PGTOPO_BE_ERROR();
6847  return -1;
6848  }
6849  LWDEBUGF(1, "New point is within %.15g units of %llu edges", tol, num);
6850  if ( num )
6851  {
6852  id = _lwt_SplitAllEdgesToNewNode(topo, edges, num, lwgeom_as_lwpoint(pt), tol, moved);
6853  _lwt_release_edges(edges, num);
6854  if ( numSplitEdges ) *numSplitEdges = num;
6855  }
6856 
6857  if ( id == 0 )
6858  {
6859  /* The point is isolated, add it as such */
6860  /* TODO: pass 1 as last argument (skipChecks) ? */
6861  id = _lwt_AddIsoNode(topo, -1, point, 0, findFace);
6862  if ( moved ) *moved = 0;
6863  if ( -1 == id )
6864  {
6865  /* should have invoked lwerror already, leaking memory */
6866  _lwt_release_edges(edges, num);
6867  lwerror("lwt_AddIsoNode failed");
6868  return -1;
6869  }
6870  }
6871 
6872  return id;
6873 }
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:372
double lwgeom_mindistance2d(const LWGEOM *lw1, const LWGEOM *lw2)
Function initializing min distance calculation.
Definition: measures.c:212
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: