Пример #1
0
Datum BOX2D_same(PG_FUNCTION_ARGS)
{
	GBOX		   *box1 = (GBOX *) PG_GETARG_POINTER(0);
	GBOX		   *box2 = (GBOX *) PG_GETARG_POINTER(1);

	PG_RETURN_BOOL(FPeq(box1->xmax, box2->xmax) &&
	               FPeq(box1->xmin, box2->xmin) &&
	               FPeq(box1->ymax, box2->ymax) &&
	               FPeq(box1->ymin, box2->ymin));
}
Пример #2
0
Datum lwgeom_lt(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom1 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
	GSERIALIZED *geom2 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
	GBOX box1;
	GBOX box2;

	POSTGIS_DEBUG(2, "lwgeom_lt called");

	if (gserialized_get_srid(geom1) != gserialized_get_srid(geom2))
	{
		elog(BTREE_SRID_MISMATCH_SEVERITY,
		     "Operation on two GEOMETRIES with different SRIDs\n");
		PG_FREE_IF_COPY(geom1, 0);
		PG_FREE_IF_COPY(geom2, 1);
		PG_RETURN_NULL();
	}

	POSTGIS_DEBUG(3, "lwgeom_lt passed getSRID test");

	gserialized_get_gbox_p(geom1, &box1);
	gserialized_get_gbox_p(geom2, &box2);

	PG_FREE_IF_COPY(geom1, 0);
	PG_FREE_IF_COPY(geom2, 1);

	POSTGIS_DEBUG(3, "lwgeom_lt getbox2d_p passed");

	if  ( ! FPeq(box1.xmin , box2.xmin) )
	{
		if  (box1.xmin < box2.xmin)
			PG_RETURN_BOOL(TRUE);
	}

	if  ( ! FPeq(box1.ymin , box2.ymin) )
	{
		if  (box1.ymin < box2.ymin)
			PG_RETURN_BOOL(TRUE);
	}

	if  ( ! FPeq(box1.xmax , box2.xmax) )
	{
		if  (box1.xmax < box2.xmax)
			PG_RETURN_BOOL(TRUE);
	}

	if  ( ! FPeq(box1.ymax , box2.ymax) )
	{
		if  (box1.ymax < box2.ymax)
			PG_RETURN_BOOL(TRUE);
	}

	PG_RETURN_BOOL(FALSE);
}
Пример #3
0
  Datum  spherepoly_add_points_finalize(PG_FUNCTION_ARGS)
  {
    SPOLY   * poly  =  ( SPOLY   * ) PG_GETARG_POINTER ( 0 ) ;
    if ( poly == NULL ){
      PG_RETURN_NULL ( );
    }

    poly = PG_GETARG_SPOLY( 0 );

    if ( poly->npts < 3 ){
      elog ( NOTICE , "spoly(spoint): At least 3 points required" );
      FREE ( poly );
      PG_RETURN_NULL ( );
    }
    // Skip if distance is equal 180deg
    if ( FPeq ( spoint_dist ( &poly->p[0], &poly->p[ poly->npts - 1 ]) , PI ) )
    {
      elog ( NOTICE , "spoly(spoint): Cannot close polygon. Distance between first and last point is 180deg" );
      FREE ( poly );
      PG_RETURN_NULL ( );
    }

    if ( !spherepoly_check ( poly ) ){
      elog ( NOTICE , "spoly(spoint): a line segment overlaps or polygon too large" );
      FREE ( poly ) ;
      PG_RETURN_NULL();
    }
    PG_RETURN_POINTER ( poly );
  }
Пример #4
0
long line_eq(LINE *l1, LINE *l2)
{
    double	k;
    
    if (! FPzero(l2->A))
	k = l1->A / l2->A;
    else if (! FPzero(l2->B))
	k = l1->B / l2->B;
    else if (! FPzero(l2->C))
	k = l1->C / l2->C;
    else
	k = 1.0;
    return( FPeq(l1->A, k * l2->A) &&
	   FPeq(l1->B, k * l2->B) &&
	   FPeq(l1->C, k * l2->C) );
}
Пример #5
0
  Datum  spherecircle_in(PG_FUNCTION_ARGS)
  {
    SCIRCLE  * c  = ( SCIRCLE * ) MALLOC ( sizeof ( SCIRCLE ) ) ;
    char     * s  = PG_GETARG_CSTRING(0);
    double lng, lat, radius ;

    void sphere_yyparse( void );

    init_buffer ( s );
    sphere_yyparse();
    if ( get_circle( &lng, &lat, &radius ) ){
      c->center.lng  = lng;
      c->center.lat  = lat;
      c->radius      = radius;
      reset_buffer();
      /*
        It's important to allow circles with radius 90deg!!      
      */
      if ( FPgt(c->radius,PIH) ){
        FREE( c );
        c = NULL;
        elog ( ERROR , "spherecircle_in: radius must be not greater than 90 degrees" );
      } else if ( FPeq(c->radius,PIH) ){
        // set "exact" 90 degrees
        c->radius = PIH;
      }
      spoint_check ( &c->center );
    } else {
      reset_buffer();
      FREE( c );
      c = NULL;
      elog ( ERROR , "spherecircle_in: parse error" );
    }
    PG_RETURN_POINTER( c );
  }
Пример #6
0
 bool scircle_eq ( const SCIRCLE * c1 , const SCIRCLE * c2 )
 {
   return ( 
    spoint_eq ( &c1->center , &c2->center ) && 
    FPeq ( c1->radius , c2->radius ) 
  ) ;
 }
Пример #7
0
static bool
gist_point_consistent_internal(StrategyNumber strategy,
							   bool isLeaf, BOX *key, Point *query)
{
	bool		result = false;

	switch (strategy)
	{
		case RTLeftStrategyNumber:
			result = FPlt(key->low.x, query->x);
			break;
		case RTRightStrategyNumber:
			result = FPgt(key->high.x, query->x);
			break;
		case RTAboveStrategyNumber:
			result = FPgt(key->high.y, query->y);
			break;
		case RTBelowStrategyNumber:
			result = FPlt(key->low.y, query->y);
			break;
		case RTSameStrategyNumber:
			if (isLeaf)
			{
				/* key.high must equal key.low, so we can disregard it */
				result = (FPeq(key->low.x, query->x) &&
						  FPeq(key->low.y, query->y));
			}
			else
			{
				result = (FPle(query->x, key->high.x) &&
						  FPge(query->x, key->low.x) &&
						  FPle(query->y, key->high.y) &&
						  FPge(query->y, key->low.y));
			}
			break;
		default:
			elog(ERROR, "unrecognized strategy number: %d", strategy);
			result = false;		/* keep compiler quiet */
			break;
	}

	return result;
}
Пример #8
0
void
spoint_check(SPoint *spoint)
{
	bool lat_is_neg = (spoint->lat < 0) ? true : false;

	if (spoint->lng < 0 || spoint->lng > PID)
		spoint->lng = spoint->lng - floor(spoint->lng / (PID)) * PID;
	if (spoint->lat < -PIH || spoint->lat > PIH)
		spoint->lat = spoint->lat - floor(spoint->lat / (PID)) * PID;
	if (spoint->lng < 0.0)
	{
		spoint->lng += (PID);
	}
	if (spoint->lat > PI)
	{
		spoint->lat -= (2 * PI);
	}
	if (spoint->lat > PIH)
	{
		spoint->lat = (PI - spoint->lat);
		spoint->lng += ((spoint->lng < PI) ? (PI) : (-PI));
	}
	if (spoint->lat < -PIH)
	{
		spoint->lat = (-PI - spoint->lat);
		spoint->lng += ((spoint->lng < PI) ? (PI) : (-PI));
	}
	if (FPeq(spoint->lat, PIH) && lat_is_neg)
		spoint->lat = -PIH;

	if (FPeq(spoint->lng, PID))
	{
		spoint->lng = 0.0;
	}
	if (FPzero(spoint->lng))
	{
		spoint->lng = 0.0;
	}
	if (FPzero(spoint->lat))
	{
		spoint->lat = 0.0;
	}
}
Пример #9
0
static bool
gist_point_consistent_internal(strat_nr_t strategy, bool isLeaf, BOX * key, Point * query)
{
	bool result = false;

	switch (strategy) {
	case RTLeftStrategyNumber:
		result = FPlt(key->low.x, query->x);
		break;

	case RTRightStrategyNumber:
		result = FPgt(key->high.x, query->x);
		break;

	case RTAboveStrategyNumber:
		result = FPgt(key->high.y, query->y);
		break;

	case RTBelowStrategyNumber:
		result = FPlt(key->low.y, query->y);
		break;

	case RTSameStrategyNumber:
		if (isLeaf) {
			result = FPeq(key->low.x, query->x)
				&& FPeq(key->low.y, query->y);
		} else {
			result = (query->x <= key->high.x
				&& query->x >= key->low.x
				&& query->y <= key->high.y
				&& query->y >= key->low.y);
		}
		break;

	default:
		elog(ERROR, "unknown strategy number: %d", strategy);
	}

	return result;
}
Пример #10
0
SPoint *  spoint_check (SPoint * spoint)
{
    static bool lat_is_neg;
    lat_is_neg = ( spoint->lat < 0 )?( TRUE ):( FALSE );

    if(spoint->lng < 0 || spoint->lng > PID)
        spoint->lng  = spoint->lng - floor(spoint->lng / ( PID ) )  * PID;
    if(spoint->lat < -PIH || spoint->lat > PIH)
        spoint->lat  = spoint->lat - floor(spoint->lat / ( PID ) )  * PID;
    if( spoint->lng < 0.0 ) {
        spoint->lng +=  ( PID );
    }
    if( spoint->lat > PI   ) {
        spoint->lat -=  ( 2*PI );
    }
    if( spoint->lat > PIH  ) {
        spoint->lat  =  ( PI - spoint->lat );
        spoint->lng +=  ( ( spoint->lng<PI )?( PI ):( -PI ) ) ;
    }
    if( spoint->lat < -PIH ) {
        spoint->lat  =  ( -PI - spoint->lat  );
        spoint->lng +=  ( ( spoint->lng<PI )?( PI ):( -PI ) ) ;
    }
    if (
        FPeq(spoint->lat,PIH) && lat_is_neg
    ) spoint->lat  = -PIH ;

    if ( FPeq(spoint->lng,PID) ) {
        spoint->lng  = 0.0 ;
    }
    if ( FPzero(spoint->lng) ) {
        spoint->lng  = 0.0 ;
    }
    if ( FPzero(spoint->lat) ) {
        spoint->lat  = 0.0 ;
    }

    return spoint;
}
Пример #11
0
  Datum  spherepoly_add_point(PG_FUNCTION_ARGS)
  {
    SPOLY   * poly  =  ( SPOLY   * ) PG_GETARG_POINTER ( 0 ) ;
    SPoint  * p     =  ( SPoint  * ) PG_GETARG_POINTER ( 1 ) ;
    int32     size  = 0 ;
    SPOLY * poly_new = NULL;

    if ( p == NULL ){
      PG_RETURN_POINTER ( poly );
    }
    if ( poly == NULL ){
      size = offsetof(SPOLY, p[0]) + sizeof(SPoint) ;
      poly = ( SPOLY * ) MALLOC ( size );
      memcpy( (void*) &poly->p[0] , (void*) p, sizeof(SPoint) );
#if PG_VERSION_NUM < 80300
      poly->size = size;
#else
      SET_VARSIZE(poly, size);
#endif
      poly->npts = 1;
      PG_RETURN_POINTER ( poly );
    }

    poly = PG_GETARG_SPOLY( 0 );

    // skip if equal
    if ( spoint_eq (p, &poly->p[ poly->npts - 1 ]) ){
      PG_RETURN_POINTER ( poly );
    }

    // Skip if distance is equal 180deg
    if ( FPeq ( spoint_dist ( p, &poly->p[ poly->npts - 1 ]) , PI ) )
    {
      elog ( NOTICE , "spoly(spoint): Skip point, distance of previous point is 180deg" );
    }

    size = offsetof(SPOLY, p[0]) + sizeof(SPoint) * ( poly->npts + 1 );
    poly_new = palloc( size );
    memcpy( (void*) poly , (void*) poly_new, VARSIZE(poly) );
    poly_new->npts++;

#if PG_VERSION_NUM < 80300
    poly_new->size = size ;
#else
    SET_VARSIZE( poly_new, size );
#endif

    memcpy( (void*) &poly_new->p[poly->npts] , (void*) p, sizeof(SPoint) );
    PG_RETURN_POINTER ( poly_new );
  }        
Пример #12
0
Datum lwgeom_eq(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom1 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
	GSERIALIZED *geom2 = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
	GBOX box1;
	GBOX box2;
	bool result;

	POSTGIS_DEBUG(2, "lwgeom_eq called");

	if (gserialized_get_srid(geom1) != gserialized_get_srid(geom2))
	{
		elog(BTREE_SRID_MISMATCH_SEVERITY,
		     "Operation on two GEOMETRIES with different SRIDs\n");
		PG_FREE_IF_COPY(geom1, 0);
		PG_FREE_IF_COPY(geom2, 1);
		PG_RETURN_NULL();
	}

	gserialized_get_gbox_p(geom1, &box1);
	gserialized_get_gbox_p(geom2, &box2);
	PG_FREE_IF_COPY(geom1, 0);
	PG_FREE_IF_COPY(geom2, 1);

	if  ( ! (FPeq(box1.xmin, box2.xmin) && FPeq(box1.ymin, box2.ymin) &&
	         FPeq(box1.xmax, box2.xmax) && FPeq(box1.ymax, box2.ymax)) )
	{
		result = FALSE;
	}
	else
	{
		result = TRUE;
	}

	PG_RETURN_BOOL(result);
}
Пример #13
0
  float8 spoint_dist ( const SPoint * p1, const SPoint * p2 )
  {
	float8 dl = p1->lng - p2->lng;
    float8 f = (  ( sin( p1->lat )*sin( p2->lat ) + cos( p1->lat )*cos( p2->lat )*cos( dl ) ) );
    if( FPeq( f, 1.0 ) ){
   	  /* for small distances */
      Vector3D v1, v2, v3;
      spoint_vector3d(&v1, p1);
      spoint_vector3d(&v2, p2);
      vector3d_cross( &v3, &v1, &v2 );
      f = vector3d_length(&v3);
    } else {
      f = acos(f);
    }
    if ( FPzero(f) ){
      return 0.0;
    } else {
      return f;
    }
  }
Пример #14
0
LINE *				/* two points */
line_construct_pp(Point *pt1, Point *pt2)
{
    LINE	*result;
    
    result = PALLOCTYPE(LINE);
    if (FPeq(pt1->x, pt2->x)) {		/* vertical */
	/* use "x = C" */
	result->m = 0.0;
	result->A = -1.0;
	result->B = 0.0;
	result->C = pt1->x;
    } else {
	/* use "mx - y + yinter = 0" */
	result->m = (pt1->y - pt2->y) / (pt1->x - pt2->x);
	result->A = result->m;
	result->B = -1.0;
	result->C = pt1->y - result->m * pt1->x;
    }
    return(result);
}
Пример #15
0
long line_vertical(LINE *line)
{
    return( FPeq(line->A, -1.0) && FPzero(line->B) );
}
Пример #16
0
long line_parallel(LINE *l1, LINE *l2)
{
    return( FPeq(l1->m, l2->m) );
}
Пример #17
0
long box_eq(BOX *box1, BOX *box2)
{
    return( FPeq(box_ar(box1), box_ar(box2)) );
}
Пример #18
0
long lseg_horizontal(LSEG *lseg)
{
    return( FPeq(lseg->p[0].y, lseg->p[1].y) );
}
Пример #19
0
Datum geography_gist_picksplit(PG_FUNCTION_ARGS)
{

	GistEntryVector	*entryvec = (GistEntryVector*) PG_GETARG_POINTER(0);

	GIST_SPLITVEC *v = (GIST_SPLITVEC*) PG_GETARG_POINTER(1);
	OffsetNumber i;
	/* One union box for each half of the space. */
	GIDX **box_union;
	/* One offset number list for each half of the space. */
	OffsetNumber **list;
	/* One position index for each half of the space. */
	int *pos;
	GIDX *box_pageunion;
	GIDX *box_current;
	int direction = -1;
	bool all_entries_equal = true;
	OffsetNumber max_offset;
	int nbytes, ndims_pageunion, d;
	int posmax = -1;

	POSTGIS_DEBUG(4, "[GIST] 'picksplit' function called");

	/*
	** First calculate the bounding box and maximum number of dimensions in this page.
	*/

	max_offset = entryvec->n - 1;
	box_current = (GIDX*) DatumGetPointer(entryvec->vector[FirstOffsetNumber].key);
	box_pageunion = gidx_copy(box_current);

	/* Calculate the containing box (box_pageunion) for the whole page we are going to split. */
	for ( i = OffsetNumberNext(FirstOffsetNumber); i <= max_offset; i = OffsetNumberNext(i) )
	{
		box_current = (GIDX*) DatumGetPointer(entryvec->vector[i].key);

		if ( all_entries_equal == true && ! gidx_equals (box_pageunion, box_current) )
			all_entries_equal = false;

		gidx_merge( &box_pageunion, box_current );
	}

	POSTGIS_DEBUGF(3, "[GIST] box_pageunion: %s", gidx_to_string(box_pageunion));

	/* Every box in the page is the same! So, we split and just put half the boxes in each child. */
	if ( all_entries_equal )
	{
		POSTGIS_DEBUG(4, "[GIST] picksplit finds all entries equal!");
		geography_gist_picksplit_fallback(entryvec, v);
		PG_RETURN_POINTER(v);
	}

	/* Initialize memory structures. */
	nbytes = (max_offset + 2) * sizeof(OffsetNumber);
	ndims_pageunion = GIDX_NDIMS(box_pageunion);
	POSTGIS_DEBUGF(4, "[GIST] ndims_pageunion == %d", ndims_pageunion);
	pos = palloc(2*ndims_pageunion * sizeof(int));
	list = palloc(2*ndims_pageunion * sizeof(OffsetNumber*));
	box_union = palloc(2*ndims_pageunion * sizeof(GIDX*));
	for ( d = 0; d < ndims_pageunion; d++ )
	{
		list[BELOW(d)] = (OffsetNumber*) palloc(nbytes);
		list[ABOVE(d)] = (OffsetNumber*) palloc(nbytes);
		box_union[BELOW(d)] = gidx_new(ndims_pageunion);
		box_union[ABOVE(d)] = gidx_new(ndims_pageunion);
		pos[BELOW(d)] = 0;
		pos[ABOVE(d)] = 0;
	}

	/*
	** Assign each entry in the node to the volume partitions it belongs to,
	** such as "above the x/y plane, left of the y/z plane, below the x/z plane".
	** Each entry thereby ends up in three of the six partitions.
	*/
	POSTGIS_DEBUG(4, "[GIST] 'picksplit' calculating best split axis");
	for ( i = FirstOffsetNumber; i <= max_offset; i = OffsetNumberNext(i) )
	{
		box_current = (GIDX*) DatumGetPointer(entryvec->vector[i].key);

		for ( d = 0; d < ndims_pageunion; d++ )
		{
			if ( GIDX_GET_MIN(box_current,d)-GIDX_GET_MIN(box_pageunion,d) < GIDX_GET_MAX(box_pageunion,d)-GIDX_GET_MAX(box_current,d) )
			{
				geography_gist_picksplit_addlist(list[BELOW(d)], &(box_union[BELOW(d)]), box_current, &(pos[BELOW(d)]), i);
			}
			else
			{
				geography_gist_picksplit_addlist(list[ABOVE(d)], &(box_union[ABOVE(d)]), box_current, &(pos[ABOVE(d)]), i);
			}

		}

	}

	/*
	** "Bad disposition", too many entries fell into one octant of the space, so no matter which
	** plane we choose to split on, we're going to end up with a mostly full node. Where the
	** data is pretty homogeneous (lots of duplicates) entries that are equidistant from the
	** sides of the page union box can occasionally all end up in one place, leading
	** to this condition.
	*/
	if ( geography_gist_picksplit_badratios(pos,ndims_pageunion) == TRUE )
	{
		/*
		** Instead we split on center points and see if we do better.
		** First calculate the average center point for each axis.
		*/
		double *avgCenter = palloc(ndims_pageunion * sizeof(double));

		for ( d = 0; d < ndims_pageunion; d++ )
		{
			avgCenter[d] = 0.0;
		}

		POSTGIS_DEBUG(4, "[GIST] picksplit can't find good split axis, trying center point method");

		for ( i = FirstOffsetNumber; i <= max_offset; i = OffsetNumberNext(i) )
		{
			box_current = (GIDX*) DatumGetPointer(entryvec->vector[i].key);
			for ( d = 0; d < ndims_pageunion; d++ )
			{
				avgCenter[d] += (GIDX_GET_MAX(box_current,d) + GIDX_GET_MIN(box_current,d)) / 2.0;
			}
		}
		for ( d = 0; d < ndims_pageunion; d++ )
		{
			avgCenter[d] /= max_offset;
			pos[BELOW(d)] = pos[ABOVE(d)] = 0; /* Re-initialize our counters. */
			POSTGIS_DEBUGF(4, "[GIST] picksplit average center point[%d] = %.12g", d, avgCenter[d]);
		}

		/* For each of our entries... */
		for ( i = FirstOffsetNumber; i <= max_offset; i = OffsetNumberNext(i) )
		{
			double center;
			box_current = (GIDX*) DatumGetPointer(entryvec->vector[i].key);

			for ( d = 0; d < ndims_pageunion; d++ )
			{
				center = (GIDX_GET_MIN(box_current,d)+GIDX_GET_MAX(box_current,d))/2.0;
				if ( center < avgCenter[d] )
					geography_gist_picksplit_addlist(list[BELOW(d)], &(box_union[BELOW(d)]), box_current, &(pos[BELOW(d)]), i);
				else if ( FPeq(center, avgCenter[d]) )
					if ( pos[BELOW(d)] > pos[ABOVE(d)] )
						geography_gist_picksplit_addlist(list[ABOVE(d)], &(box_union[ABOVE(d)]), box_current, &(pos[ABOVE(d)]), i);
					else
						geography_gist_picksplit_addlist(list[BELOW(d)], &(box_union[BELOW(d)]), box_current, &(pos[BELOW(d)]), i);
				else
					geography_gist_picksplit_addlist(list[ABOVE(d)], &(box_union[ABOVE(d)]), box_current, &(pos[ABOVE(d)]), i);
			}

		}

		/* Do we have a good disposition now? If not, screw it, just cut the node in half. */
		if ( geography_gist_picksplit_badratios(pos,ndims_pageunion) == TRUE )
		{
			POSTGIS_DEBUG(4, "[GIST] picksplit still cannot find a good split! just cutting the node in half");
			geography_gist_picksplit_fallback(entryvec, v);
			PG_RETURN_POINTER(v);
		}

	}

	/*
	** Now, what splitting plane gives us the most even ratio of
	** entries in our child pages? Since each split region has been apportioned entries
	** against the same number of total entries, the axis that has the smallest maximum
	** number of entries in its regions is the most evenly distributed.
	** TODO: what if the distributions are equal in two or more axes?
	*/
	for ( d = 0; d < ndims_pageunion; d++ )
	{
		int posd = Max(pos[ABOVE(d)],pos[BELOW(d)]);
		if ( posd > posmax )
		{
			direction = d;
			posmax = posd;
		}
	}
	if ( direction == -1 || posmax == -1 )
	{
		/* ERROR OUT HERE */
		elog(ERROR, "Error in building split, unable to determine split direction.");
	}

	POSTGIS_DEBUGF(3, "[GIST] 'picksplit' splitting on axis %d", direction);

	geography_gist_picksplit_constructsplit(v, list[BELOW(direction)],
	                                        pos[BELOW(direction)],
	                                        &(box_union[BELOW(direction)]),
	                                        list[ABOVE(direction)],
	                                        pos[ABOVE(direction)],
	                                        &(box_union[ABOVE(direction)]) );

	POSTGIS_DEBUGF(4, "[GIST] spl_ldatum: %s", gidx_to_string((GIDX*)v->spl_ldatum));
	POSTGIS_DEBUGF(4, "[GIST] spl_rdatum: %s", gidx_to_string((GIDX*)v->spl_rdatum));

	POSTGIS_DEBUGF(4, "[GIST] axis %d: parent range (%.12g, %.12g) left range (%.12g, %.12g), right range (%.12g, %.12g)",
	               direction,
	               GIDX_GET_MIN(box_pageunion, direction), GIDX_GET_MAX(box_pageunion, direction),
	               GIDX_GET_MIN((GIDX*)v->spl_ldatum, direction), GIDX_GET_MAX((GIDX*)v->spl_ldatum, direction),
	               GIDX_GET_MIN((GIDX*)v->spl_rdatum, direction), GIDX_GET_MAX((GIDX*)v->spl_rdatum, direction) );

	PG_RETURN_POINTER(v);

}
Пример #20
0
long lseg_parallel(LSEG *l1, LSEG *l2)
{
    return( FPeq(l1->m, l2->m) );
}
Пример #21
0
  /*!
    \brief Converts an array of spherical points to SPOLY
    \param arr pointer to array of spherical points
    \param nelem count of elements
    \return pointer to created spherical polygon
  */
  static SPOLY * spherepoly_from_array ( SPoint * arr, int32 nelem )
  {

    SPOLY  * poly = NULL;

    if ( nelem < 3 ){
      elog ( ERROR , "spherepoly_from_array: more than two points needed" );
      return NULL;
    } else {

      static int32  i;
      static float8 scheck ;
      int32      size;

      for ( i=0; i<nelem ; i++ ){
        spoint_check ( &arr[i] );
      }

      // check duplicate points
      i = 0;
      while ( i<(nelem-1) ){
        if ( nelem < 3 ) break;
        if ( spoint_eq (&arr[i],&arr[i+1]) ){
          if ( i<(nelem-2) ){
            memmove ((void*) &arr[i+1], (void*) &arr[i+2], (nelem-i-2) * sizeof( SPoint ) );
          }
          nelem--;
          continue;
        }
        i++;
      }
      if ( spoint_eq (&arr[0],&arr[nelem-1]) ){
        nelem--;
      }
      if ( nelem < 3 ){
        elog ( ERROR , "spherepoly_from_array: more than two points needed" );
        return NULL;
      }

      size       = offsetof(SPOLY, p[0]) + sizeof(SPoint) * nelem;
      poly       = (SPOLY *) MALLOC ( size ) ;
      SET_VARSIZE(poly, size);
      poly->npts = nelem;
      for ( i=0; i<nelem ; i++ ){
        if ( i==0 ){
          scheck = spoint_dist ( &arr[nelem-1], &arr[0] );
        } else {
          scheck = spoint_dist ( &arr[i-1]    , &arr[i] );
        }
        if (FPeq(scheck,PI)){
          elog ( ERROR , "spherepoly_from_array: a polygon segment length must be not equal 180 degrees." );
          return NULL;
        }
        memcpy( (void*) &poly->p[i], (void*) &arr[i], sizeof( SPoint ) );
      }

    }

    if ( ! spherepoly_check ( poly ) ){
      elog ( ERROR , "spherepoly_from_array: a line segment overlaps or polygon too large" );
      FREE ( poly ) ;
      return NULL;
    }

    return ( poly );

  }
Пример #22
0
long point_vert(Point *pt1, Point *pt2)
{
    return( FPeq( pt1->x, pt2->x ) );
}
Пример #23
0
long lseg_vertical(LSEG *lseg)
{
    return( FPeq(lseg->p[0].x, lseg->p[1].x) );
}
Пример #24
0
long point_horiz(Point *pt1, Point *pt2)
{
    return( FPeq( pt1->y, pt2->y ) );
}
Пример #25
0
  bool spoly_contains_point ( const SPOLY * pg , const SPoint * sp )
  {
    static int32   i;
    static SLine   sl;
    bool    res = FALSE ;
    static float8  scp;
    static Vector3D vc, vp;

    // First check, if point is outside polygon (behind)
    spherepoly_center  ( &vc , pg );
    spoint_vector3d    ( &vp , sp );
    scp = vector3d_scalar ( &vp , &vc );
    if ( FPle ( scp, 0.0 ) ){
      return false;
    }

    // Check whether point is edge
    for ( i=0; i<pg->npts; i++ ){
      if ( spoint_eq ( &pg->p[i] , sp ) ){
        return TRUE;
      }
    }
    
    // Check whether point is on a line segment
    for ( i=0; i<pg->npts; i++ ){
      spoly_segment ( &sl , pg , i );
      if ( spoint_at_sline( sp, &sl ) ){
        return TRUE;
      }
    }

    do {

      SEuler se, te;
      SPoint p , lp[2];
      bool   a1, a2, eqa ;
      int32  cntr = 0;
      SPOLY * tmp = ( SPOLY * ) MALLOC ( VARSIZE(pg) );

      /*
        Make a transformation, so point is (0,0)
      */

      se.phi_a   = EULER_AXIS_Z  ;
      se.theta_a = EULER_AXIS_X  ;
      se.psi_a   = EULER_AXIS_Z  ;
      se.phi     = PIH - sp->lng ;
      se.theta   = - sp->lat     ;
      se.psi     = -PIH          ;

      euler_spoly_trans ( tmp , pg , &se );

      p.lng = 0.0;
      p.lat = 0.0;

      // Check, whether an edge is on equator.
      // If yes, rotate randomized around 0,0

      cntr = 0;
      do {
        eqa = FALSE;
        for ( i=0; i<pg->npts; i++ ){
          if ( FPzero(tmp->p[i].lat) ){
            if ( FPeq( cos(tmp->p[i].lng) , -1.0 ) ){
              return false;
            } else {
              eqa = TRUE;
              break;
            }
          }
        }
        if ( eqa ){
          SPOLY * ttt = ( SPOLY * ) MALLOC ( VARSIZE(pg) );
          srand( cntr );
          se.phi_a   = se.theta_a = se.psi_a = EULER_AXIS_X  ;
          se.phi     = ( (double) rand() / RAND_MAX ) * PID ;
          se.theta   = 0.0  ;
          se.psi     = 0.0  ;
          euler_spoly_trans ( ttt , tmp , &se );
          memcpy ( (void*) tmp, (void*) ttt, VARSIZE(pg) );
          FREE(ttt);
        }
        if ( cntr>10000 ){
          elog(WARNING ,"Bug found in spoly_contains_point");
          elog(ERROR   ,"Please report it to pg_sphere team!");
          return false;
        }
        cntr++;
      } while ( eqa );

      // Count line segment crossing "equator"

      cntr = 0;
      for ( i=0; i<pg->npts; i++ ){

        // create a single line from segment
        spoly_segment ( &sl , tmp , i );

        sline_begin ( &lp[0], &sl );
        sline_end   ( &lp[1], &sl );

        a1  = ( FPgt(lp[0].lat,0.0) && FPlt(lp[1].lat,0.0) );
        a2  = ( FPlt(lp[0].lat,0.0) && FPgt(lp[1].lat,0.0) );

        if ( a1 || a2 ){ // if crossing
          sphereline_to_euler_inv ( &te, &sl );
          if ( a2 ){ // crossing ascending 
            p.lng = PID - te.phi;
          } else {
            p.lng = PI - te.phi;
          }
          spoint_check ( &p );
          if ( p.lng < PI ){ // crossing between 0 and 180 deg
            cntr++;
          }
        }          
      }

      FREE ( tmp );
      if ( cntr % 2 ){
        res = TRUE;
      }        

    } while (0);

    return res;
  }