void projection::inverse(double & x,double & y) const { #ifdef MAPNIK_USE_PROJ4 if (!proj_) { throw std::runtime_error("projection::inverse not supported unless proj4 is initialized"); } #if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 mapnik::scoped_lock lock(mutex_); #endif if (is_geographic_) { x *=DEG_TO_RAD; y *=DEG_TO_RAD; } projUV p; p.u = x; p.v = y; p = pj_inv(p,proj_); x = RAD_TO_DEG * p.u; y = RAD_TO_DEG * p.v; #else throw std::runtime_error("projection::inverse not supported without proj4 support (-DMAPNIK_USE_PROJ4)"); #endif }
void project_inv(int *n, double *x, double *y, double *xlon, double *ylat, char **projarg){ /* call the _inverse_ projection specified by the string projarg, * returning longitude and lat in xlon and ylat vectors, given the * numbers in x and y vectors (all vectors of length n) */ int i; projUV p; projPJ pj; if (!(pj = pj_init_plus(*projarg))) error(pj_strerrno(*pj_get_errno_ref())); /* Rprintf("%s\n", pj_get_def(pj, 0));*/ for(i=0;i<*n;i++){ if(ISNAN(x[i]) || ISNAN(y[i])){ xlon[i]=x[i]; ylat[i]=y[i]; } else { p.u=x[i]; p.v=y[i]; p = pj_inv(p, pj); if (p.u == HUGE_VAL || ISNAN(p.u)) { Rprintf("inverse projected point not finite\n"); } xlon[i]=p.u * RAD_TO_DEG; ylat[i]=p.v * RAD_TO_DEG; } } pj_free(pj); }
void GeoConvHelper::cartesian2geo(Position& cartesian) const { cartesian.sub(getOffsetBase()); if (myProjectionMethod == NONE) { return; } if (myProjectionMethod == SIMPLE) { const double y = cartesian.y() / 111136.; const double x = cartesian.x() / 111320. / cos(DEG2RAD(y)); cartesian.set(x, y); return; } #ifdef PROJ_API_FILE #ifdef PROJ_VERSION_MAJOR PJ_COORD c; c.xy.x = cartesian.x(); c.xy.y = cartesian.y(); c = proj_trans(myProjection, PJ_INV, c); cartesian.set(proj_todeg(c.lp.lam), proj_todeg(c.lp.phi)); #else projUV p; p.u = cartesian.x(); p.v = cartesian.y(); p = pj_inv(p, myProjection); //!!! check pj_errno p.u *= RAD_TO_DEG; p.v *= RAD_TO_DEG; cartesian.set((double) p.u, (double) p.v); #endif #endif }
/* * NAME: * fmucs2geo * * PURPOSE: * Computes geographical latitude, longitude from UCS northings, eastings. * * REQUIREMENTS: * * INPUT: * * OUTPUT: * * NOTES: * * BUGS: * * AUTHOR: * Øystein Godøy, met.no/FOU, 10.01.2005 * * MODIFIED: * NA */ fmgeopos fmucs2geo(fmucspos xy, fmprojspec myproj) { fmgeopos ll; PJ *ref; projUV cnat; /* * Select predefined projection, and initialize interface to PROJ */ if (myproj == MI) { if (!(ref=pj_init(sizeof(miproj)/sizeof(char *), miproj))) { fprintf(stderr,"ERROR: PROJ initialization failed.\n"); } } else if (myproj == MEOS) { if (!(ref=pj_init(sizeof(meosproj)/sizeof(char *), meosproj))) { fprintf(stderr,"ERROR: PROJ initialization failed.\n"); } } else { fprintf(stdout,"ERROR: Projection not supported\n"); } /* * Estimate ll */ cnat.u = xy.eastings; cnat.v = xy.northings; cnat = pj_inv(cnat,ref); ll.lon = cnat.u*RAD_TO_DEG; ll.lat = cnat.v*RAD_TO_DEG; if (cnat.u == HUGE_VAL) { fprintf(stderr, "ERROR: pj_inv conversion\n"); } pj_free(ref); return(ll); }
static bool TransformTiffCorner(GTIF * gtif, GTIFDefn * defn, double x, double y, double& outLon, double& outLat) { /* Try to transform the coordinate into PCS space */ if( !GTIFImageToPCS( gtif, &x, &y ) ) return false; if( defn->Model == ModelTypeGeographic ) { outLon = x; outLat = y; return true; } else { if( GTIFProj4ToLatLong( defn, 1, &x, &y ) ) { outLon = x; outLat = y; return true; } int size = 0; tagtype_t type = TYPE_UNKNOWN; int key_count = GTIFKeyInfo(gtif, GTCitationGeoKey, &size, &type); if(key_count > 0 && key_count < 1024 && type == TYPE_ASCII && size == 1) { vector<char> ascii(key_count); int r = GTIFKeyGet(gtif, GTCitationGeoKey, &ascii[0], 0, key_count); if(r == key_count) { DebugAssert(ascii.back() == 0); string citation = string(&ascii[0]); if(citation == "PCS Name = WGS_1984_Web_Mercator_Auxiliary_Sphere") { char ** args = CSLTokenizeStringComplex("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs", " +", TRUE, FALSE); PJ * psPJ = pj_init( CSLCount(args), args ); CSLDestroy(args); if(psPJ) { projUV sUV; sUV.u = x; sUV.v = y; sUV = pj_inv( sUV, psPJ ); outLon = sUV.u * RAD_TO_DEG; outLat = sUV.v * RAD_TO_DEG; pj_free(psPJ); return true; } } } } } return false; }
//------------------------------------------------------------------------------- void Projection_libproj::screen2map(int i, int j, double *x, double *y) const { projUV data, res; data.u = ((i-W/2.0)/scale+ CX)*111319.0 ; data.v = ((H/2.0-j)/scale+ CY)*111319.0 ; res = pj_inv(data, libProj); *x = (double)(res.u*RAD_TO_DEG); *y = (double)(res.v*RAD_TO_DEG); //printf("PROJ screen2map (%3d %3d) -> (%f %f)\n", i,j, *x,*y); }
/*--------------------------------------------------------------------*/ int mb_proj_inverse(int verbose, void *pjptr, double easting, double northing, double *lon, double *lat, int *error) { char *function_name = "mb_proj_inverse"; int status = MB_SUCCESS; projPJ pj; projUV pjxy; projUV pjll; /* print input debug statements */ if (verbose >= 2) { fprintf(stderr,"\ndbg2 MBIO function <%s> called\n",function_name); fprintf(stderr,"dbg2 Revision id: %s\n",rcs_id); fprintf(stderr,"dbg2 Input arguments:\n"); fprintf(stderr,"dbg2 verbose: %d\n",verbose); fprintf(stderr,"dbg2 pjptr: %p\n",(void *)pjptr); fprintf(stderr,"dbg2 easting: %f\n",easting); fprintf(stderr,"dbg2 northing: %f\n",northing); } /* do forward projection */ if (pjptr != NULL) { pj = (projPJ) pjptr; pjxy.u = easting; pjxy.v = northing; pjll = pj_inv(pjxy, pj); *lon = RTD * pjll.u; *lat = RTD * pjll.v; } /* assume success */ *error = MB_ERROR_NO_ERROR; status = MB_SUCCESS; /* print output debug statements */ if (verbose >= 2) { fprintf(stderr,"\ndbg2 MBIO function <%s> completed\n",function_name); fprintf(stderr,"dbg2 Revision id: %s\n",rcs_id); fprintf(stderr,"dbg2 Return values:\n"); fprintf(stderr,"dbg2 lon: %f\n",*lon); fprintf(stderr,"dbg2 lat: %f\n",*lat); fprintf(stderr,"dbg2 error: %d\n",*error); fprintf(stderr,"dbg2 Return status:\n"); fprintf(stderr,"dbg2 status: %d\n",status); } /* return status */ return(status); }
inline bool inverse(const XY& xy, LL& lp) const { try { pj_inv(this->m_prj, this->m_par, xy, lp); return true; } catch(...) { return false; } }
//Goes from the projected coordinates to WGS84 LatLon static VALUE proj_inverse(VALUE self,VALUE uv){ _wrap_pj* wpj; projUV* c_uv; projUV* pResult; Data_Get_Struct(self,_wrap_pj,wpj); Data_Get_Struct(uv,projUV,c_uv); pResult = (projUV*) malloc(sizeof(projUV)); *pResult = pj_inv(*c_uv,wpj->pj); pResult->u *= RAD_TO_DEG; pResult->v *= RAD_TO_DEG; return Data_Wrap_Struct(cUV,0,uv_free,pResult); }
projUV* c_pj_inv_ptr(projUV *val, projPJ proj) { projUV res; # ifdef _DEBUG printf("Entered c_pj_inv_ptr(proj=%p).\n", proj); # endif res = pj_inv(*val, proj); val->u = res.u; val->v = res.v; return val; }
int GTIFProj4ToLatLong( GTIFDefn * psDefn, int nPoints, double *padfX, double *padfY ) { char *pszProjection, **papszArgs; PJ *psPJ; int i; /* -------------------------------------------------------------------- */ /* Get a projection definition. */ /* -------------------------------------------------------------------- */ pszProjection = GTIFGetProj4Defn( psDefn ); if( pszProjection == NULL ) return FALSE; /* -------------------------------------------------------------------- */ /* Parse into tokens for pj_init(), and initialize the projection. */ /* -------------------------------------------------------------------- */ papszArgs = CSLTokenizeStringComplex( pszProjection, " +", TRUE, FALSE ); free( pszProjection ); psPJ = pj_init( CSLCount(papszArgs), papszArgs ); CSLDestroy( papszArgs ); if( psPJ == NULL ) { return FALSE; } /* -------------------------------------------------------------------- */ /* Process each of the points. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nPoints; i++ ) { UV sUV; sUV.u = padfX[i]; sUV.v = padfY[i]; sUV = pj_inv( sUV, psPJ ); padfX[i] = sUV.u * RAD_TO_DEG; padfY[i] = sUV.v * RAD_TO_DEG; } pj_free( psPJ ); return TRUE; }
static void projection_inverse (GfsMap * map, const FttVector * src, FttVector * dest) { projLP odata; projXY idata; GfsMapProjection * m = GFS_MAP_PROJECTION (map); gdouble L = gfs_object_simulation (map)->physical_params.L; idata.u = (src->x*m->cosa + src->y*m->sina)*L; idata.v = (src->y*m->cosa - src->x*m->sina)*L; odata = pj_inv (idata, GFS_MAP_PROJECTION (map)->pj); dest->x = odata.u*RAD_TO_DEG/L; dest->y = odata.v*RAD_TO_DEG/L; dest->z = src->z; }
/** * Project an X/Y pair to a latitude/longitude pair * * @param p The proj-based projector to use. * @param y The Y part of the pair (metres). * @param x The X part of the pair (metres). * @return The spherical coordinates. */ spherical_coordinates _proj_inverse_project(projector *p, float y, float x) { // Construct a proj-compatible input projUV pj_input; pj_input.u = y; pj_input.v = x; // Project the coordinates projUV pj_output = pj_inv(pj_input, (projUV *) p->internals); // Convert the result back to degrees spherical_coordinates output = {pj_output.v * RAD_TO_DEG, pj_output.u * RAD_TO_DEG}; return output; }
void GeoConvHelper::cartesian2geo(Position& cartesian) const { cartesian.sub(getOffsetBase()); if (myProjectionMethod == NONE) { return; } #ifdef HAVE_PROJ projUV p; p.u = cartesian.x(); p.v = cartesian.y(); p = pj_inv(p, myProjection); //!!! check pj_errno p.u *= RAD_TO_DEG; p.v *= RAD_TO_DEG; cartesian.set((SUMOReal) p.u, (SUMOReal) p.v); #endif }
void UTMToLonLat(double x, double y, int zone, double * outLon, double * outLat) { SetupUTMMap(zone); if (sUTMProj.find(zone) == sUTMProj.end()) return; projUV sUV; sUV.u = x; sUV.v = y; // sUV = nad_cvt(sUV, false, sNADGrid); sUV = pj_inv( sUV, sUTMProj[zone]); if (outLon) *outLon = sUV.u * RAD_TO_DEG; if (outLat) *outLat = sUV.v * RAD_TO_DEG; }
projXY S57_prj2geo(projUV uv) // convert PROJ to geographic (LL) { if (TRUE == _doInit) return uv; if (NULL == _pjdst) return uv; uv = pj_inv(uv, _pjdst); if (0 != pj_errno) { PRINTF("ERROR: x=%f y=%f %s\n", uv.u, uv.v, pj_strerrno(pj_errno)); g_assert(0); return uv; } uv.u /= DEG_TO_RAD; uv.v /= DEG_TO_RAD; return uv; }
/**Transforms a point in the coordinate system defined at initialization of the Projection object to WGS84 LonLat in radians. This version of the method changes the point in-place. call-seq: inverse!(point) -> point */ static VALUE proj_inverse(VALUE self,VALUE point){ _wrap_pj* wpj; int pj_errno_ref; projXY pj_point; projLP pj_result; Data_Get_Struct(self,_wrap_pj,wpj); pj_point.u = NUM2DBL( rb_funcall(point, idGetX, 0) ); pj_point.v = NUM2DBL( rb_funcall(point, idGetY, 0) ); pj_result = pj_inv(pj_point, wpj->pj); pj_errno_ref = *pj_get_errno_ref(); if (pj_errno_ref == 0) { rb_funcall(point, idSetX, 1, rb_float_new(pj_result.u) ); rb_funcall(point, idSetY, 1, rb_float_new(pj_result.v) ); return point; } else if (pj_errno_ref > 0) { rb_raise(rb_eSystemCallError, "Unknown system call error"); } else { raise_error(pj_errno_ref); } return self; /* Makes gcc happy */ }
static void process(FILE *fid) { char line[MAX_LINE], *s, t, pline[100]; projUV val; double tmp; for (;;) { if (input.bin) fread(&val, sizeof(projUV), 1, fid); else if (s = fgets(line, MAX_LINE, fid)) { if (*s == tag) { fputs(line, stdout); continue; } else if (input.ll) { val.u = dmstor(s, &s); val.v = dmstor(s, &s); } else { val.u = strtod(s, &s); val.v = strtod(s, &s); } } if (feof(fid)) break; if (input.rev) { tmp = val.u; val.u = val.v; val.v = tmp; } /* data in, manupulate */ if (input.cnv) val = pj_inv(val, input.cnv); if (input.hp) val = nad_cvt(val, 1, htab); /* nad conversion */ if (ctab) val = nad_cvt(val, input.t83 ? 1 : 0, ctab); if (output.hp) val = nad_cvt(val, 0, htab); if (output.cnv) val = pj_fwd(val, output.cnv); /* output data */ if (output.rev) { tmp = val.u; val.u = val.v; val.v = tmp; } if (output.bin) (void)fwrite(&val, sizeof(projUV), 1, stdout); else { if (echoin) { t = *s; *s = '\0'; (void)fputs(line, stdout); (void)putchar('\t'); *s = t; } if (val.u == HUGE_VAL) (void)fputs(oterr, stdout); else if (output.ll) if (oform) { (void)printf(oform, val.u * RAD_TO_DEG); (void)putchar('\t'); (void)printf(oform, val.v * RAD_TO_DEG); } else if (output.rev) { (void)fputs(rtodms(pline, val.u, 'N', 'S'), stdout); (void)putchar('\t'); (void)fputs(rtodms(pline, val.v, 'E', 'W'), stdout); } else { (void)fputs(rtodms(pline, val.u, 'E', 'W'), stdout); (void)putchar('\t'); (void)fputs(rtodms(pline, val.v, 'N', 'S'), stdout); } else { (void)printf(oform ? oform : "%.2f", val.u); (void)putchar('\t'); (void)printf(oform ? oform : "%.2f", val.v); } if (input.bin) putchar('\n'); else (void)fputs(s, stdout); } } }
int msProjectPoint(projectionObj *in, projectionObj *out, pointObj *point) { #ifdef USE_PROJ projUV p; int error; if( in && in->gt.need_geotransform ) { double x_out, y_out; x_out = in->gt.geotransform[0] + in->gt.geotransform[1] * point->x + in->gt.geotransform[2] * point->y; y_out = in->gt.geotransform[3] + in->gt.geotransform[4] * point->x + in->gt.geotransform[5] * point->y; point->x = x_out; point->y = y_out; } /* -------------------------------------------------------------------- */ /* If the source and destination are simple and equal, then do */ /* nothing. */ /* -------------------------------------------------------------------- */ if( in && in->numargs == 1 && out && out->numargs == 1 && strcmp(in->args[0],out->args[0]) == 0 ) { /* do nothing, no transformation required */ } /* -------------------------------------------------------------------- */ /* If we have a fully defined input coordinate system and */ /* output coordinate system, then we will use pj_transform. */ /* -------------------------------------------------------------------- */ else if( in && in->proj && out && out->proj ) { double z = 0.0; if( pj_is_latlong(in->proj) ) { point->x *= DEG_TO_RAD; point->y *= DEG_TO_RAD; } msAcquireLock( TLOCK_PROJ ); error = pj_transform( in->proj, out->proj, 1, 0, &(point->x), &(point->y), &z ); msReleaseLock( TLOCK_PROJ ); if( error || point->x == HUGE_VAL || point->y == HUGE_VAL ) return MS_FAILURE; if( pj_is_latlong(out->proj) ) { point->x *= RAD_TO_DEG; point->y *= RAD_TO_DEG; } } /* -------------------------------------------------------------------- */ /* Otherwise we fallback to using pj_fwd() or pj_inv() and */ /* assuming that the NULL projectionObj is supposed to be */ /* lat/long in the same datum as the other projectionObj. This */ /* is essentially a backwards compatibility mode. */ /* -------------------------------------------------------------------- */ else { /* nothing to do if the other coordinate system is also lat/long */ if( in == NULL && out != NULL && pj_is_latlong(out->proj) ) return MS_SUCCESS; if( out == NULL && in != NULL && pj_is_latlong(in->proj) ) return MS_SUCCESS; p.u = point->x; p.v = point->y; if(in==NULL || in->proj==NULL) { /* input coordinates are lat/lon */ p.u *= DEG_TO_RAD; /* convert to radians */ p.v *= DEG_TO_RAD; p = pj_fwd(p, out->proj); } else { if(out==NULL || out->proj==NULL) { /* output coordinates are lat/lon */ p = pj_inv(p, in->proj); p.u *= RAD_TO_DEG; /* convert to decimal degrees */ p.v *= RAD_TO_DEG; } else { /* need to go from one projection to another */ p = pj_inv(p, in->proj); p = pj_fwd(p, out->proj); } } if( p.u == HUGE_VAL || p.v == HUGE_VAL ) return MS_FAILURE; point->x = p.u; point->y = p.v; } if( out && out->gt.need_geotransform ) { double x_out, y_out; x_out = out->gt.invgeotransform[0] + out->gt.invgeotransform[1] * point->x + out->gt.invgeotransform[2] * point->y; y_out = out->gt.invgeotransform[3] + out->gt.invgeotransform[4] * point->x + out->gt.invgeotransform[5] * point->y; point->x = x_out; point->y = y_out; } return(MS_SUCCESS); #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectPoint()"); return(MS_FAILURE); #endif }
int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, double *x, double *y, double *z ) { long i; int need_datum_shift; pj_errno = 0; if( point_offset == 0 ) point_offset = 1; /* -------------------------------------------------------------------- */ /* Transform geocentric source coordinates to lat/long. */ /* -------------------------------------------------------------------- */ if( srcdefn->is_geocent ) { if( z == NULL ) { pj_errno = PJD_ERR_GEOCENTRIC; return PJD_ERR_GEOCENTRIC; } if( srcdefn->to_meter != 1.0 ) { for( i = 0; i < point_count; i++ ) { if( x[point_offset*i] != HUGE_VAL ) { x[point_offset*i] *= srcdefn->to_meter; y[point_offset*i] *= srcdefn->to_meter; } } } if( pj_geocentric_to_geodetic( srcdefn->a_orig, srcdefn->es_orig, point_count, point_offset, x, y, z ) != 0) return pj_errno; } /* -------------------------------------------------------------------- */ /* Transform source points to lat/long, if they aren't */ /* already. */ /* -------------------------------------------------------------------- */ else if( !srcdefn->is_latlong ) { if( srcdefn->inv == NULL ) { pj_errno = -17; /* this isn't correct, we need a no inverse err */ if( getenv( "PROJ_DEBUG" ) != NULL ) { fprintf( stderr, "pj_transform(): source projection not invertable\n" ); } return pj_errno; } for( i = 0; i < point_count; i++ ) { XY projected_loc; LP geodetic_loc; projected_loc.u = x[point_offset*i]; projected_loc.v = y[point_offset*i]; if( projected_loc.u == HUGE_VAL ) continue; geodetic_loc = pj_inv( projected_loc, srcdefn ); if( pj_errno != 0 ) { if( (pj_errno != 33 /*EDOM*/ && pj_errno != 34 /*ERANGE*/ ) && (pj_errno > 0 || pj_errno < -44 || point_count == 1 || transient_error[-pj_errno] == 0 ) ) return pj_errno; else { geodetic_loc.u = HUGE_VAL; geodetic_loc.v = HUGE_VAL; } } x[point_offset*i] = geodetic_loc.u; y[point_offset*i] = geodetic_loc.v; } } /* -------------------------------------------------------------------- */ /* But if they are already lat long, adjust for the prime */ /* meridian if there is one in effect. */ /* -------------------------------------------------------------------- */ if( srcdefn->from_greenwich != 0.0 ) { for( i = 0; i < point_count; i++ ) { if( x[point_offset*i] != HUGE_VAL ) x[point_offset*i] += srcdefn->from_greenwich; } } /* -------------------------------------------------------------------- */ /* Convert datums if needed, and possible. */ /* -------------------------------------------------------------------- */ if( pj_datum_transform( srcdefn, dstdefn, point_count, point_offset, x, y, z ) != 0 ) return pj_errno; /* -------------------------------------------------------------------- */ /* But if they are staying lat long, adjust for the prime */ /* meridian if there is one in effect. */ /* -------------------------------------------------------------------- */ if( dstdefn->from_greenwich != 0.0 ) { for( i = 0; i < point_count; i++ ) { if( x[point_offset*i] != HUGE_VAL ) x[point_offset*i] -= dstdefn->from_greenwich; } } /* -------------------------------------------------------------------- */ /* Transform destination latlong to geocentric if required. */ /* -------------------------------------------------------------------- */ if( dstdefn->is_geocent ) { if( z == NULL ) { pj_errno = PJD_ERR_GEOCENTRIC; return PJD_ERR_GEOCENTRIC; } pj_geodetic_to_geocentric( dstdefn->a_orig, dstdefn->es_orig, point_count, point_offset, x, y, z ); if( dstdefn->fr_meter != 1.0 ) { for( i = 0; i < point_count; i++ ) { if( x[point_offset*i] != HUGE_VAL ) { x[point_offset*i] *= dstdefn->fr_meter; y[point_offset*i] *= dstdefn->fr_meter; } } } } /* -------------------------------------------------------------------- */ /* Transform destination points to projection coordinates, if */ /* desired. */ /* -------------------------------------------------------------------- */ else if( !dstdefn->is_latlong ) { for( i = 0; i < point_count; i++ ) { XY projected_loc; LP geodetic_loc; geodetic_loc.u = x[point_offset*i]; geodetic_loc.v = y[point_offset*i]; if( geodetic_loc.u == HUGE_VAL ) continue; projected_loc = pj_fwd( geodetic_loc, dstdefn ); if( pj_errno != 0 ) { if( (pj_errno != 33 /*EDOM*/ && pj_errno != 34 /*ERANGE*/ ) && (pj_errno > 0 || pj_errno < -44 || point_count == 1 || transient_error[-pj_errno] == 0 ) ) return pj_errno; else { projected_loc.u = HUGE_VAL; projected_loc.v = HUGE_VAL; } } x[point_offset*i] = projected_loc.u; y[point_offset*i] = projected_loc.v; } } /* -------------------------------------------------------------------- */ /* If a wrapping center other than 0 is provided, rewrap around */ /* the suggested center (for latlong coordinate systems only). */ /* -------------------------------------------------------------------- */ else if( dstdefn->is_latlong && dstdefn->long_wrap_center != 0 ) { for( i = 0; i < point_count; i++ ) { if( x[point_offset*i] == HUGE_VAL ) continue; while( x[point_offset*i] < dstdefn->long_wrap_center - HALFPI ) x[point_offset*i] += PI; while( x[point_offset*i] > dstdefn->long_wrap_center + HALFPI ) x[point_offset*i] -= PI; } } return 0; }
int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, double *x, double *y, double *z ) { long i; int need_datum_shift; pj_errno = 0; if( point_offset == 0 ) point_offset = 1; /* -------------------------------------------------------------------- */ /* Transform source points to lat/long, if they aren't */ /* already. */ /* -------------------------------------------------------------------- */ if( !srcdefn->is_latlong ) { for( i = 0; i < point_count; i++ ) { XY projected_loc; LP geodetic_loc; projected_loc.u = x[point_offset*i]; projected_loc.v = y[point_offset*i]; geodetic_loc = pj_inv( projected_loc, srcdefn ); if( pj_errno != 0 ) return pj_errno; x[point_offset*i] = geodetic_loc.u; y[point_offset*i] = geodetic_loc.v; } } /* -------------------------------------------------------------------- */ /* Convert datums if needed, and possible. */ /* -------------------------------------------------------------------- */ if( pj_datum_transform( srcdefn, dstdefn, point_count, point_offset, x, y, z ) != 0 ) return pj_errno; /* -------------------------------------------------------------------- */ /* Transform destination points to projection coordinates, if */ /* desired. */ /* -------------------------------------------------------------------- */ if( !dstdefn->is_latlong ) { for( i = 0; i < point_count; i++ ) { XY projected_loc; LP geodetic_loc; geodetic_loc.u = x[point_offset*i]; geodetic_loc.v = y[point_offset*i]; projected_loc = pj_fwd( geodetic_loc, dstdefn ); if( pj_errno != 0 ) return pj_errno; x[point_offset*i] = projected_loc.u; y[point_offset*i] = projected_loc.v; } } return 0; }
int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, double *x, double *y, double *z ) { long i; int err; srcdefn->ctx->last_errno = 0; dstdefn->ctx->last_errno = 0; if( point_offset == 0 ) point_offset = 1; /* -------------------------------------------------------------------- */ /* Transform unusual input coordinate axis orientation to */ /* standard form if needed. */ /* -------------------------------------------------------------------- */ if( strcmp(srcdefn->axis,"enu") != 0 ) { int err; err = pj_adjust_axis( srcdefn->ctx, srcdefn->axis, 0, point_count, point_offset, x, y, z ); if( err != 0 ) return err; } /* -------------------------------------------------------------------- */ /* Transform Z to meters if it isn't already. */ /* -------------------------------------------------------------------- */ if( srcdefn->vto_meter != 1.0 && z != NULL ) { for( i = 0; i < point_count; i++ ) z[point_offset*i] *= srcdefn->vto_meter; } /* -------------------------------------------------------------------- */ /* Transform geocentric source coordinates to lat/long. */ /* -------------------------------------------------------------------- */ if( srcdefn->is_geocent ) { if( z == NULL ) { pj_ctx_set_errno( pj_get_ctx(srcdefn), PJD_ERR_GEOCENTRIC); return PJD_ERR_GEOCENTRIC; } if( srcdefn->to_meter != 1.0 ) { for( i = 0; i < point_count; i++ ) { if( x[point_offset*i] != HUGE_VAL ) { x[point_offset*i] *= srcdefn->to_meter; y[point_offset*i] *= srcdefn->to_meter; } } } err = pj_geocentric_to_geodetic( srcdefn->a_orig, srcdefn->es_orig, point_count, point_offset, x, y, z ); if( err != 0 ) return err; } /* -------------------------------------------------------------------- */ /* Transform source points to lat/long, if they aren't */ /* already. */ /* -------------------------------------------------------------------- */ else if( !srcdefn->is_latlong ) { if( srcdefn->inv == NULL ) { pj_ctx_set_errno( pj_get_ctx(srcdefn), -17 ); pj_log( pj_get_ctx(srcdefn), PJ_LOG_ERROR, "pj_transform(): source projection not invertable" ); return -17; } for( i = 0; i < point_count; i++ ) { XY projected_loc; LP geodetic_loc; projected_loc.u = x[point_offset*i]; projected_loc.v = y[point_offset*i]; if( projected_loc.u == HUGE_VAL ) continue; geodetic_loc = pj_inv( projected_loc, srcdefn ); if( srcdefn->ctx->last_errno != 0 ) { if( (srcdefn->ctx->last_errno != 33 /*EDOM*/ && srcdefn->ctx->last_errno != 34 /*ERANGE*/ ) && (srcdefn->ctx->last_errno > 0 || srcdefn->ctx->last_errno < -44 || point_count == 1 || transient_error[-srcdefn->ctx->last_errno] == 0 ) ) return srcdefn->ctx->last_errno; else { geodetic_loc.u = HUGE_VAL; geodetic_loc.v = HUGE_VAL; } } x[point_offset*i] = geodetic_loc.u; y[point_offset*i] = geodetic_loc.v; } } /* -------------------------------------------------------------------- */ /* But if they are already lat long, adjust for the prime */ /* meridian if there is one in effect. */ /* -------------------------------------------------------------------- */ if( srcdefn->from_greenwich != 0.0 ) { for( i = 0; i < point_count; i++ ) { if( x[point_offset*i] != HUGE_VAL ) x[point_offset*i] += srcdefn->from_greenwich; } } /* -------------------------------------------------------------------- */ /* Do we need to translate from geoid to ellipsoidal vertical */ /* datum? */ /* -------------------------------------------------------------------- */ if( srcdefn->has_geoid_vgrids ) { if( pj_apply_vgridshift( srcdefn, "sgeoidgrids", &(srcdefn->vgridlist_geoid), &(srcdefn->vgridlist_geoid_count), 0, point_count, point_offset, x, y, z ) != 0 ) return pj_ctx_get_errno(srcdefn->ctx); } /* -------------------------------------------------------------------- */ /* Convert datums if needed, and possible. */ /* -------------------------------------------------------------------- */ if( pj_datum_transform( srcdefn, dstdefn, point_count, point_offset, x, y, z ) != 0 ) { if( srcdefn->ctx->last_errno != 0 ) return srcdefn->ctx->last_errno; else return dstdefn->ctx->last_errno; } /* -------------------------------------------------------------------- */ /* Do we need to translate from geoid to ellipsoidal vertical */ /* datum? */ /* -------------------------------------------------------------------- */ if( dstdefn->has_geoid_vgrids ) { if( pj_apply_vgridshift( dstdefn, "sgeoidgrids", &(dstdefn->vgridlist_geoid), &(dstdefn->vgridlist_geoid_count), 1, point_count, point_offset, x, y, z ) != 0 ) return dstdefn->ctx->last_errno; } /* -------------------------------------------------------------------- */ /* But if they are staying lat long, adjust for the prime */ /* meridian if there is one in effect. */ /* -------------------------------------------------------------------- */ if( dstdefn->from_greenwich != 0.0 ) { for( i = 0; i < point_count; i++ ) { if( x[point_offset*i] != HUGE_VAL ) x[point_offset*i] -= dstdefn->from_greenwich; } } /* -------------------------------------------------------------------- */ /* Transform destination latlong to geocentric if required. */ /* -------------------------------------------------------------------- */ if( dstdefn->is_geocent ) { if( z == NULL ) { pj_ctx_set_errno( dstdefn->ctx, PJD_ERR_GEOCENTRIC ); return PJD_ERR_GEOCENTRIC; } pj_geodetic_to_geocentric( dstdefn->a_orig, dstdefn->es_orig, point_count, point_offset, x, y, z ); if( dstdefn->fr_meter != 1.0 ) { for( i = 0; i < point_count; i++ ) { if( x[point_offset*i] != HUGE_VAL ) { x[point_offset*i] *= dstdefn->fr_meter; y[point_offset*i] *= dstdefn->fr_meter; } } } } /* -------------------------------------------------------------------- */ /* Transform destination points to projection coordinates, if */ /* desired. */ /* -------------------------------------------------------------------- */ else if( !dstdefn->is_latlong ) { for( i = 0; i < point_count; i++ ) { XY projected_loc; LP geodetic_loc; geodetic_loc.u = x[point_offset*i]; geodetic_loc.v = y[point_offset*i]; if( geodetic_loc.u == HUGE_VAL ) continue; projected_loc = pj_fwd( geodetic_loc, dstdefn ); if( dstdefn->ctx->last_errno != 0 ) { if( (dstdefn->ctx->last_errno != 33 /*EDOM*/ && dstdefn->ctx->last_errno != 34 /*ERANGE*/ ) && (dstdefn->ctx->last_errno > 0 || dstdefn->ctx->last_errno < -44 || point_count == 1 || transient_error[-dstdefn->ctx->last_errno] == 0 ) ) return dstdefn->ctx->last_errno; else { projected_loc.u = HUGE_VAL; projected_loc.v = HUGE_VAL; } } x[point_offset*i] = projected_loc.u; y[point_offset*i] = projected_loc.v; } } /* -------------------------------------------------------------------- */ /* If a wrapping center other than 0 is provided, rewrap around */ /* the suggested center (for latlong coordinate systems only). */ /* -------------------------------------------------------------------- */ else if( dstdefn->is_latlong && dstdefn->is_long_wrap_set ) { for( i = 0; i < point_count; i++ ) { if( x[point_offset*i] == HUGE_VAL ) continue; while( x[point_offset*i] < dstdefn->long_wrap_center - PI ) x[point_offset*i] += TWOPI; while( x[point_offset*i] > dstdefn->long_wrap_center + PI ) x[point_offset*i] -= TWOPI; } } /* -------------------------------------------------------------------- */ /* Transform Z from meters if needed. */ /* -------------------------------------------------------------------- */ if( dstdefn->vto_meter != 1.0 && z != NULL ) { for( i = 0; i < point_count; i++ ) z[point_offset*i] *= dstdefn->vfr_meter; } /* -------------------------------------------------------------------- */ /* Transform normalized axes into unusual output coordinate axis */ /* orientation if needed. */ /* -------------------------------------------------------------------- */ if( strcmp(dstdefn->axis,"enu") != 0 ) { int err; err = pj_adjust_axis( dstdefn->ctx, dstdefn->axis, 1, point_count, point_offset, x, y, z ); if( err != 0 ) return err; } return 0; }
/* file processing function --- verbosely */ static void vprocess(FILE *fid) { char line[MAX_LINE+3], *s, pline[40]; PJ_LP dat_ll; PJ_XY dat_xy; int linvers; PJ_COORD coord; if (!oform) oform = "%.3f"; if (bin_in || bin_out) emess(1,"binary I/O not available in -V option"); for (;;) { proj_errno_reset(Proj); ++emess_dat.File_line; if (!(s = fgets(line, MAX_LINE, fid))) break; if (!strchr(s, '\n')) { /* overlong line */ int c; (void)strcat(s, "\n"); /* gobble up to newline */ while ((c = fgetc(fid)) != EOF && c != '\n') ; } if (*s == tag) { /* pass on data */ (void)fputs(s, stdout); continue; } /* check to override default input mode */ if (*s == 'I' || *s == 'i') { linvers = 1; ++s; } else linvers = inverse; if (linvers) { if (!PJ_INVERS(Proj)) { emess(-1,"inverse for this projection not avail.\n"); continue; } dat_xy.x = strtod(s, &s); dat_xy.y = strtod(s, &s); if (dat_xy.x == HUGE_VAL || dat_xy.y == HUGE_VAL) { emess(-1,"lon-lat input conversion failure\n"); continue; } if (prescale) { dat_xy.x *= fscale; dat_xy.y *= fscale; } if (reversein) { PJ_XY temp = dat_xy; dat_xy.x = temp.y; dat_xy.y = temp.x; } dat_ll = pj_inv(dat_xy, Proj); } else { dat_ll.lam = proj_dmstor(s, &s); dat_ll.phi = proj_dmstor(s, &s); if (dat_ll.lam == HUGE_VAL || dat_ll.phi == HUGE_VAL) { emess(-1,"lon-lat input conversion failure\n"); continue; } if (reversein) { PJ_LP temp = dat_ll; dat_ll.lam = temp.phi; dat_ll.phi = temp.lam; } dat_xy = pj_fwd(dat_ll, Proj); if (postscale) { dat_xy.x *= fscale; dat_xy.y *= fscale; } } /* For some reason pj_errno does not work as expected in some */ /* versions of Visual Studio, so using pj_get_errno_ref instead */ if (*pj_get_errno_ref()) { emess(-1, pj_strerrno(*pj_get_errno_ref())); continue; } if (!*s && (s > line)) --s; /* assumed we gobbled \n */ coord.lp = dat_ll; facs = proj_factors(Proj, coord); if (proj_errno(Proj)) { emess(-1,"failed to compute factors\n\n"); continue; } if (*s != '\n') (void)fputs(s, stdout); (void)fputs("Longitude: ", stdout); (void)fputs(proj_rtodms(pline, dat_ll.lam, 'E', 'W'), stdout); (void)printf(" [ %.11g ]\n", dat_ll.lam * RAD_TO_DEG); (void)fputs("Latitude: ", stdout); (void)fputs(proj_rtodms(pline, dat_ll.phi, 'N', 'S'), stdout); (void)printf(" [ %.11g ]\n", dat_ll.phi * RAD_TO_DEG); (void)fputs("Easting (x): ", stdout); (void)printf(oform, dat_xy.x); putchar('\n'); (void)fputs("Northing (y): ", stdout); (void)printf(oform, dat_xy.y); putchar('\n'); (void)printf("Meridian scale (h) : %.8f ( %.4g %% error )\n", facs.meridional_scale, (facs.meridional_scale-1.)*100.); (void)printf("Parallel scale (k) : %.8f ( %.4g %% error )\n", facs.parallel_scale, (facs.parallel_scale-1.)*100.); (void)printf("Areal scale (s): %.8f ( %.4g %% error )\n", facs.areal_scale, (facs.areal_scale-1.)*100.); (void)printf("Angular distortion (w): %.3f\n", facs.angular_distortion * RAD_TO_DEG); (void)printf("Meridian/Parallel angle: %.5f\n", facs.meridian_parallel_angle * RAD_TO_DEG); (void)printf("Convergence : "); (void)fputs(proj_rtodms(pline, facs.meridian_convergence, 0, 0), stdout); (void)printf(" [ %.8f ]\n", facs.meridian_convergence * RAD_TO_DEG); (void)printf("Max-min (Tissot axis a-b) scale error: %.5f %.5f\n\n", facs.tissot_semimajor, facs.tissot_semiminor); } }
static void write_shapefile (local_data_t *local_data) { guint npolys; char *shape_filename; SHPHandle shape_file = NULL; SHPObject *shape; double *vertex_x, *vertex_y; guint i, j; projUV p; char *dbf_filename; DBFHandle dbf_file = NULL; int nunits_field_index; int avg_ninfected_field_index; int avg_ndestroyed_field_index; int avg_nvaccinated_field_index; int avg_frinfected_field_index; int avg_frdestroyed_field_index; int avg_frvaccinated_field_index; #if DEBUG g_debug ("----- ENTER write_shapefile (%s)", MODEL_NAME); #endif vertex_x = g_new (double, local_data->max_nvertices); vertex_y = g_new (double, local_data->max_nvertices); /* We are going to write 2 files: the .shp file, containing the geometry of * the polygons, and the .dbf file, containing the numeric attributes * attached to the polygons. */ shape_filename = g_strdup_printf ("%s.shp", local_data->base_filename); #if DEBUG g_debug ("creating new shapefile \"%s\"", shape_filename); #endif shape_file = SHPCreate (shape_filename, SHPT_POLYGON); g_assert (shape_file != NULL); npolys = local_data->polys->len; for (i = 0; i < npolys; i++) { gpc_polygon *poly; gpc_vertex_list *contour; poly = (gpc_polygon *) g_ptr_array_index (local_data->polys, i); g_assert (poly->num_contours == 1); contour = &(poly->contour[0]); for (j = 0; j < contour->num_vertices; j++) { /* The polygon vertices are in x-y coordinates. We need to * "unproject" them back to lat-long. */ p.u = contour->vertex[j].x; p.v = contour->vertex[j].y; p = pj_inv (p, local_data->projection); vertex_x[j] = p.u * RAD_TO_DEG; vertex_y[j] = p.v * RAD_TO_DEG; } shape = SHPCreateSimpleObject (SHPT_POLYGON, j, vertex_x, vertex_y, NULL); SHPWriteObject (shape_file, -1, shape); SHPDestroyObject (shape); } if (shape_file != NULL) SHPClose (shape_file); g_free (shape_filename); /* Now the attribute file */ dbf_filename = g_strdup_printf ("%s.dbf", local_data->base_filename); #if DEBUG g_debug ("creating new attributes file \"%s\"", dbf_filename); #endif dbf_file = DBFCreate (dbf_filename); g_assert (dbf_file != NULL); /* Add attribute definitions. */ #if DEBUG g_debug ("adding field definitions to DBF file \"%s\": nunits, avgninf, avgndest, avgnvacc, avgfrinf, avgfrdest, avgfrvacc", dbf_filename); #endif /* 9-digit integers should be enough to count # of units in a polygon. */ nunits_field_index = DBFAddField (dbf_file, "nunits", FTInteger, 9, 0); /* 1 decimal place for average # of units infected or destroyed, 3 for * average fraction of units. */ avg_ninfected_field_index = DBFAddField (dbf_file, "avgninf", FTDouble, 9, 1); avg_ndestroyed_field_index = DBFAddField (dbf_file, "avgndest", FTDouble, 9, 1); avg_nvaccinated_field_index = DBFAddField (dbf_file, "avgnvacc", FTDouble, 9, 1); avg_frinfected_field_index = DBFAddField (dbf_file, "avgfrinf", FTDouble, 9, 3); avg_frdestroyed_field_index = DBFAddField (dbf_file, "avgfrdest", FTDouble, 9, 3); avg_frvaccinated_field_index = DBFAddField (dbf_file, "avgfrvacc", FTDouble, 9, 3); /* Write the attributes to the file. */ #if DEBUG g_debug ("writing attributes to \"%s\"", dbf_filename); #endif for (i = 0; i < npolys; i++) { guint nunits; /* Divide the counts by the number of runs to get the mean */ local_data->ninfected[i] /= local_data->nruns; local_data->ndestroyed[i] /= local_data->nruns; local_data->nvaccinated[i] /= local_data->nruns; nunits = local_data->unit_count[i]; DBFWriteIntegerAttribute (dbf_file, i, nunits_field_index, nunits); DBFWriteDoubleAttribute (dbf_file, i, avg_ninfected_field_index, local_data->ninfected[i]); DBFWriteDoubleAttribute (dbf_file, i, avg_ndestroyed_field_index, local_data->ndestroyed[i]); DBFWriteDoubleAttribute (dbf_file, i, avg_nvaccinated_field_index, local_data->nvaccinated[i]); DBFWriteDoubleAttribute (dbf_file, i, avg_frinfected_field_index, local_data->ninfected[i] / nunits); DBFWriteDoubleAttribute (dbf_file, i, avg_frdestroyed_field_index, local_data->ndestroyed[i] / nunits); DBFWriteDoubleAttribute (dbf_file, i, avg_frvaccinated_field_index, local_data->nvaccinated[i] / nunits); } if (dbf_file != NULL) DBFClose (dbf_file); g_free (dbf_filename); /* Clean up. */ g_free (vertex_y); g_free (vertex_x); #if DEBUG g_debug ("----- EXIT write_shapefile (%s)", MODEL_NAME); #endif return; }