SEuler * seuler_trans_zxz ( SEuler * out , const SEuler * in , const SEuler * se ) { static SPoint sp[4] ; sp[0].lng = 0.0; sp[0].lat = 0.0; sp[1].lng = PIH; sp[1].lat = 0.0; euler_spoint_trans ( &sp[2], &sp[0], in ); euler_spoint_trans ( &sp[3], &sp[1], in ); euler_spoint_trans ( &sp[0], &sp[2], se ); euler_spoint_trans ( &sp[1], &sp[3], se ); spherevector_to_euler ( out , &sp[0], &sp[1] ); return out; }
/* * 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; }
Datum spheretrans_point(PG_FUNCTION_ARGS) { SPoint * sp = ( SPoint * ) PG_GETARG_POINTER ( 0 ) ; SEuler * se = ( SEuler * ) PG_GETARG_POINTER ( 1 ) ; SPoint * out = ( SPoint * ) MALLOC ( sizeof ( SPoint ) ); PG_RETURN_POINTER ( euler_spoint_trans ( out , sp , se ) ); }
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] ) ); }
Datum spherepoly_area(PG_FUNCTION_ARGS) { SPOLY * poly = PG_GETARG_SPOLY( 0 ) ; int32 i; SPoint s[poly->npts + 2]; SPoint stmp[2]; SEuler se; float8 sum = 0.0; memcpy( (void*)&s[1], (void*)&poly->p[0] , poly->npts * sizeof( SPoint ) ); memcpy( (void*)&s[0], (void*)&s[poly->npts] , sizeof( SPoint ) ); memcpy( (void*)&s[poly->npts+1], (void*)&s[1] , sizeof( SPoint ) ); se.psi = 0; se.phi_a = EULER_AXIS_Z; se.theta_a = EULER_AXIS_X; se.psi_a = EULER_AXIS_Z; for ( i=1; i<=poly->npts; i++ ){ se.phi = -PIH - s[i].lng ; se.theta = s[i].lat - PIH ; euler_spoint_trans( &stmp[0] , &s[i-1] , &se ); euler_spoint_trans( &stmp[1] , &s[i+1] , &se ); stmp[1].lng -= stmp[0].lng; if ( FPlt(stmp[1].lng,0.0) ){ stmp[1].lng += PID; } sum += stmp[1].lng ; } sum -= ( PI * ( poly->npts - 2 ) ) ; if ( FPge(sum,PID) ){ sum = 2*PID - sum; } if ( FPzero(sum) ){ sum = 0.0; } PG_RETURN_FLOAT8 ( sum ); }
/*! \brief Does a transformation of polygon using Euler transformation \param se pointer to Euler transformation \param in pointer to polygon \param out pointer to transformed polygon \return pointer to transformed polygon */ static SPOLY * euler_spoly_trans ( SPOLY * out , const SPOLY * in , const SEuler * se ) { int32 i; out->size = in->size; out->npts = in->npts; for ( i=0; i<in->npts ; i++ ){ euler_spoint_trans ( &out->p[i] , &in->p[i] , se ); } return out ; }
/*! \brief Checks crossing of line segments \param poly pointer to polygon \return true if crossing */ static bool spherepoly_check ( const SPOLY * poly ) { int32 i, k ; SLine sli, slk; Vector3D v ; SPoint p; SEuler se; int8 pos; spherepoly_center ( &v , poly ); // If 0-vector if ( FPzero(v.x) && FPzero(v.y) && FPzero(v.z) ){ return FALSE; } for ( i=0; i<poly->npts; i++ ){ spoly_segment ( &sli , poly , i ); for ( k=(i+1); k<poly->npts; k++ ){ spoly_segment ( &slk , poly , k ); pos = sline_sline_pos( &sli, &slk ); if ( ! ( pos == PGS_LINE_CONNECT || pos == PGS_LINE_AVOID ) ) { return FALSE; } } } vector3d_spoint ( &p , &v ); se.phi_a = EULER_AXIS_Z ; se.theta_a = EULER_AXIS_X ; se.psi_a = EULER_AXIS_Z ; se.phi = -PIH - p.lng ; se.theta = p.lat - PIH ; se.psi = 0.0 ; for ( i=0; i<poly->npts; i++ ){ euler_spoint_trans ( &p , &poly->p[i], &se ); // less _and_ equal are important !! // Do not change it! if ( FPle(p.lat,0.0) ) { return FALSE; } } return TRUE ; }
SCIRCLE * euler_scircle_trans ( SCIRCLE * out , const SCIRCLE * in , const SEuler * se ) { euler_spoint_trans ( &out->center , &in->center , se ); out->radius = in->radius; return out; }