コード例 #1
0
ファイル: polygon.c プロジェクト: mnullmei/pgsphere
  bool spoly_eq ( const SPOLY * p1, const SPOLY * p2, bool dir )
  {
    bool    ret = FALSE;

    if ( p1->npts == p2->npts ){

      int32   i, k, cntr, shift;

      for ( shift=0; shift<p1->npts; shift++ ) {
        cntr = 0;
        for ( i=0; i<p1->npts; i++ ){
          k = (dir)?( p1->npts - i - 1 ):(i); 
          k += shift;
          k = (k<p1->npts)?(k):(k - p1->npts);
          if ( spoint_eq ( &p1->p[i], &p2->p[k]) ){
            cntr++;
          }
        }
        if ( cntr == p1->npts ){
          ret = TRUE;
          break;
        }
      }

      // Try other direction, if not equal
      if ( !dir && !ret ){
        ret = spoly_eq ( p1, p2, TRUE );
      }

    }

    return ret;  
  }
コード例 #2
0
ファイル: euler.c プロジェクト: akorotkov/pgsphere
 /*
  * Transforms a spherical vector from 'spb' to 'spe' into an inverse Euler
  * transformation. Returns true if the transformation was successful.
  */
static bool
spherevector_to_euler_inv(SEuler *se, const SPoint *spb, const SPoint *spe)
{
	if (spoint_eq(spb, spe))
	{
		return false;
	}
	else
	{
		Vector3D	vbeg, vend, vtmp;
		SPoint		spt[2];
		SEuler		set;

		spoint_vector3d(&vbeg, spb);
		spoint_vector3d(&vend, spe);
		vector3d_cross(&vtmp, &vbeg, &vend);
		vector3d_spoint(&spt[0], &vtmp);
		set.phi = -spt[0].lng - PIH;
		set.theta = spt[0].lat - PIH;
		set.psi = 0.0;
		seuler_set_zxz(&set);
		euler_spoint_trans(&spt[1], spb, &set);
		set.psi = -spt[1].lng;
		memcpy((void *) se, (void *) &set, sizeof(SEuler));
	}

	return true;
}
コード例 #3
0
ファイル: euler.c プロジェクト: china-vo/pgSphere
  bool strans_eq ( const SEuler * e1, const SEuler * e2 )
  {
    static SPoint in[2], p[4] ;

    in[0].lng  = 0.0;
    in[0].lat  = 0.0;
    in[1].lng  = PIH;
    in[1].lat  = 0.0;

    euler_spoint_trans ( &p[0] , &in[0] , e1 );
    euler_spoint_trans ( &p[1] , &in[1] , e1 );
    euler_spoint_trans ( &p[2] , &in[0] , e2 );
    euler_spoint_trans ( &p[3] , &in[1] , e2 );

    return ( spoint_eq ( &p[0], &p[2] ) && spoint_eq ( &p[1], &p[3] ) );
  }
コード例 #4
0
ファイル: circle.c プロジェクト: china-vo/pgSphere
 bool scircle_eq ( const SCIRCLE * c1 , const SCIRCLE * c2 )
 {
   return ( 
    spoint_eq ( &c1->center , &c2->center ) && 
    FPeq ( c1->radius , c2->radius ) 
  ) ;
 }
コード例 #5
0
ファイル: point.c プロジェクト: akorotkov/pgsphere
Datum
spherepoint_equal(PG_FUNCTION_ARGS)
{
	SPoint	   *p1 = (SPoint *) PG_GETARG_POINTER(0);
	SPoint	   *p2 = (SPoint *) PG_GETARG_POINTER(1);

	PG_RETURN_BOOL(spoint_eq(p1, p2));
}
コード例 #6
0
ファイル: polygon.c プロジェクト: china-vo/pgSphere
  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 );
  }        
コード例 #7
0
ファイル: polygon.c プロジェクト: mnullmei/pgsphere
  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;
  }
コード例 #8
0
ファイル: polygon.c プロジェクト: mnullmei/pgsphere
  /*!
    \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 );

  }