#ifndef IPIN_SCALER_H #define IPIN_SCALER_H #include #include struct IPIN { double lat; double lon; double floorNr; IPIN(const double lat, const double lon, const double floorNr) : lat(lat), lon(lon), floorNr(floorNr) {;} }; class IPINScaler { private: int w; int h; double cenLat; double cenLon; double rotDeg; double mPerPx; Point2 mapCenter_m; double refLat; double m_per_deg_lat; double m_per_deg_lon; const float fixedFloorHeight = 4.0f; public: /** image width, image height, map-center (lat/lon), map-rotation, meter<->pixel conversion factor */ IPINScaler(int w, int h, double cenLat, double cenLon, double rotDeg, double mPerPx) : w(w), h(h), cenLat(cenLat), cenLon(cenLon), rotDeg(rotDeg), mPerPx(mPerPx) { mapCenter_m = Point2( (w*mPerPx/2), (h*mPerPx/2) ); refLat = cenLat / 180.0 * M_PI; m_per_deg_lat = 111132.954 - 559.822 * std::cos( 2.0 * refLat ) + 1.175 * std::cos( 4.0 * refLat); m_per_deg_lon = 111132.954 * std::cos ( refLat ); } /** convert from (x,y,z) to (lat,lon,floorNr) */ IPIN toIPIN3(const float x, const float y, const float z) const { Point2 pos(x,y); // move to (0,0) pos -= mapCenter_m; // undo the rotation pos = pos.rotated(-rotDeg / 180 * M_PI); const double lat = cenLat + (pos.y / m_per_deg_lat); const double lon = cenLon + (pos.x / m_per_deg_lon); const double floorNr = z / fixedFloorHeight; return IPIN(lat, lon, floorNr); } IPIN toIPIN3(const Point3 p) const { return toIPIN3(p.x, p.y, p.z); } Point3 convert3D(const IPIN& ipin) const { return convert3D(ipin.lat, ipin.lon, ipin.floorNr); } Point3 convert3D(double lat, double lon, float floorNr) const { Point2 p2 = convert2D(lat, lon); return Point3(p2.x, p2.y, floorNr * fixedFloorHeight); } Point2 convert2D(double lat, double lon) const { const double y_m = +(lat-cenLat) * m_per_deg_lat; const double x_m = +(lon-cenLon) * m_per_deg_lon; // rotate (our map is axis aligned) Point2 pos(x_m, y_m); pos = pos.rotated(rotDeg / 180 * M_PI); // apply movement pos += mapCenter_m; return pos; } }; #endif // IPIN_SCALER_H