コード例 #1
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;
}
コード例 #2
0
ファイル: point.c プロジェクト: mnullmei/pgsphere
bool spoint_eq ( const SPoint * p1 , const SPoint * p2 )
{
    Vector3D a,b ;
    spoint_vector3d ( &a , p1 );
    spoint_vector3d ( &b , p2 );
    return ( vector3d_eq ( &a, &b ) );
}
コード例 #3
0
ファイル: point.c プロジェクト: mnullmei/pgsphere
Datum  spherepoint_z(PG_FUNCTION_ARGS)
{
    SPoint  * p =  ( SPoint * ) PG_GETARG_POINTER ( 0 ) ;
    static Vector3D  v ;
    spoint_vector3d ( &v , p );
    PG_RETURN_FLOAT8 ( v.z   );
}
コード例 #4
0
ファイル: polygon.c プロジェクト: mnullmei/pgsphere
  /*!
    \brief "Center" of a polygon
    \param v pointer to center of polygon
    \param poly pointer to polygon
    \return true if crossing
  */
  static Vector3D *  spherepoly_center ( Vector3D * v , const SPOLY * poly )
  {
    int32 i ;
    Vector3D v1, v2;
    
    v1.x =  2.0;
    v1.y =  2.0;
    v1.z =  2.0;
    v2.x = -2.0;
    v2.y = -2.0;
    v2.z = -2.0;
    
    for ( i=0; i<poly->npts; i++ ){
      spoint_vector3d ( v , &poly->p[i] );
      v1.x = min(v->x,v1.x);
      v1.y = min(v->y,v1.y);
      v1.z = min(v->z,v1.z);
      v2.x = max(v->x,v2.x);
      v2.y = max(v->y,v2.y);
      v2.z = max(v->z,v2.z);
    }

    v->x = ( v1.x + v2.x ) / 2.0 ;
    v->y = ( v1.y + v2.y ) / 2.0 ;
    v->z = ( v1.z + v2.z ) / 2.0 ;

    return v ;
  }
コード例 #5
0
ファイル: euler.c プロジェクト: china-vo/pgSphere
 SPoint  * euler_spoint_trans ( SPoint * out , const SPoint  * in , const SEuler * se )
 {
   Vector3D v,o ;
   spoint_vector3d ( &v , in );
   euler_vector_trans ( &o , &v , se );
   vector3d_spoint ( out , &o );
   return out;
 }
コード例 #6
0
ファイル: point.c プロジェクト: china-vo/pgSphere
  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;
    }
  }
コード例 #7
0
ファイル: point.c プロジェクト: china-vo/pgSphere
 Datum  spherepoint_xyz(PG_FUNCTION_ARGS)
 {
   SPoint  * p =  ( SPoint * ) PG_GETARG_POINTER ( 0 ) ;
   Datum    dret[3];
   ArrayType  *result;
   static Vector3D  v ;
   spoint_vector3d ( &v , p );    
   dret[0] = Float8GetDatumFast(v.x);
   dret[1] = Float8GetDatumFast(v.y);
   dret[2] = Float8GetDatumFast(v.z);
   result = construct_array ( dret , 3, FLOAT8OID, sizeof(float8), false /* float8 byval */ , 'd' );
   PG_RETURN_ARRAYTYPE_P(result);                                                                                                          
 }
コード例 #8
0
ファイル: point.c プロジェクト: akorotkov/pgsphere
Datum
spherepoint_xyz(PG_FUNCTION_ARGS)
{
	SPoint	   *p = (SPoint *) PG_GETARG_POINTER(0);
	Datum		dret[3];
	ArrayType  *result;
	Vector3D	v;

	spoint_vector3d(&v, p);
	dret[0] = Float8GetDatumFast(v.x);
	dret[1] = Float8GetDatumFast(v.y);
	dret[2] = Float8GetDatumFast(v.z);
#ifdef USE_FLOAT8_BYVAL
	result = construct_array(dret, 3, FLOAT8OID, sizeof(float8), true, 'd');
#else
	result = construct_array(dret, 3, FLOAT8OID, sizeof(float8), false, 'd');
#endif
	PG_RETURN_ARRAYTYPE_P(result);
}
コード例 #9
0
ファイル: key.c プロジェクト: mnullmei/pgsphere
  int32 * spherepoint_gen_key (  int32 * k , const SPoint * sp )
  {

    Vector3D            v ;
    static const int32 ks =  MAXCVALUE ;

    spoint_vector3d ( &v, sp );

    if ( v.x < -1.0 ) v.x = -1.0;
    if ( v.y < -1.0 ) v.y = -1.0;
    if ( v.z < -1.0 ) v.z = -1.0;
    if ( v.x >  1.0 ) v.x =  1.0;
    if ( v.y >  1.0 ) v.y =  1.0;
    if ( v.z >  1.0 ) v.z =  1.0;

    k[0] = v.x * ks;
    k[1] = v.y * ks;
    k[2] = v.z * ks;
    k[3] = v.x * ks;
    k[4] = v.y * ks;
    k[5] = v.z * ks;

    return ( k );
  }
コード例 #10
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;
  }
コード例 #11
0
ファイル: key.c プロジェクト: mnullmei/pgsphere
  int32 * sphereline_gen_key ( int32 * k , const SLine * sl )
  {

    static const int32         ks =  MAXCVALUE ;
    static SPoint p[3] ;

    sline_begin ( &p[0], sl );
    sline_end   ( &p[1], sl );
    
    if ( FPzero(sl->length) ){

      static Vector3D  vbeg , vend ;
      spoint_vector3d ( &vbeg , &p[0] );
      spoint_vector3d ( &vend , &p[1] );

      k[0] = min(vbeg.x,vend.x) * ks;
      k[1] = min(vbeg.y,vend.y) * ks;
      k[2] = min(vbeg.z,vend.z) * ks;
      k[3] = max(vbeg.x,vend.x) * ks;
      k[4] = max(vbeg.y,vend.y) * ks;
      k[5] = max(vbeg.z,vend.z) * ks;

    } else {

      static Vector3D  v[4], vt, vr[2] ;
      static SEuler    se ;
      static float8    l, ls, lc ;
      static int8      i;

      sphereline_to_euler ( &se, sl );
      l  = sl->length / 2.0 ; 
      ls = sin(l);
      lc = cos(l);
      se.phi += l;

      v[0].x =  lc ;
      v[0].y =  ((lc<0)?(-1.0):(-ls)) ;
      v[1].x =  1.0;
      v[1].y =  ((lc<0)?(-1.0):(-ls)) ;
      v[2].x =  lc ;
      v[2].y =  ((lc<0)?(+1.0):(+ls)) ;
      v[3].x =  1.0;
      v[3].y =  ((lc<0)?(+1.0):(+ls)) ;
      v[0].z = v[1].z = v[2].z = v[3].z = 0.0;

      vr[0].x  = vr[0].y = vr[0].z =  1.0;
      vr[1].x  = vr[1].y = vr[1].z = -1.0;

      for ( i=0; i<4; i++ ){
        euler_vector_trans(&vt,&v[i],&se);
        if ( vt.x < -1.0 ) vt.x = -1.0;
        if ( vt.y < -1.0 ) vt.y = -1.0;
        if ( vt.z < -1.0 ) vt.z = -1.0;
        if ( vt.x >  1.0 ) vt.x =  1.0;
        if ( vt.y >  1.0 ) vt.y =  1.0;
        if ( vt.z >  1.0 ) vt.z =  1.0;
        vr[0].x = min ( vr[0].x , vt.x );
        vr[1].x = max ( vr[1].x , vt.x );
        vr[0].y = min ( vr[0].y , vt.y );
        vr[1].y = max ( vr[1].y , vt.y );
        vr[0].z = min ( vr[0].z , vt.z );
        vr[1].z = max ( vr[1].z , vt.z );
      }

      k[0] = vr[0].x * ks;
      k[1] = vr[0].y * ks;
      k[2] = vr[0].z * ks;
      k[3] = vr[1].x * ks;
      k[4] = vr[1].y * ks;
      k[5] = vr[1].z * ks;

    }

    return k;
  }