#ifndef _Geom_Coords_Coords_h_ #define _Geom_Coords_Coords_h_ #include #include NAMESPACE_UPP #define MINRAD (DEGRAD / 60.0) #define SECRAD (DEGRAD / 3600.0) #define ANGDEG(d, m, s) ((d) + (m) / 60.0 + (s) / 3600.0) #define ANGRAD(d, m, s) (DEGRAD * ANGDEG((d), (m), (s))) double DegreeStep(double min_degrees); int GisLengthDecimals(double pixel_len); int DegreeDecimals(double pixel_angle); String FormatDegree(double degrees, int decimals); Value ScanDegree(const char *p); int DegreeMask(double start_angle, double end_angle); enum { AM_E0 = 1, AM_E1 = 2, AM_E2 = 4, AM_E3 = 8, AM_Q0 = 16, AM_Q1 = 32, AM_Q2 = 64, AM_Q3 = 128 }; Rectf DegreeToExtent(const Rectf& eps_rho); inline Rectf DegreeToExtent(double minphi, double minrho, double maxphi, double maxrho) { return DegreeToExtent(Rectf(minphi, minrho, maxphi, maxrho)); } Rectf ExtentToDegree(const Rectf& xy); inline double SafeArcCos(double d) { return d <= -1 ? M_PI : d >= 1 ? 0 : acos(d); } inline double SafeArcCos(double d, bool turn) { return turn ? -SafeArcCos(d) : SafeArcCos(d); } inline double SafeArcSin(double d) { return d <= -1 ? -M_PI / 2 : d >= 1 ? +M_PI / 2 : asin(d); } inline double Determinant(double a1, double a2, double a3, double b1, double b2, double b3, double c1, double c2, double c3) { return a1 * (b2 * c3 - b3 * c2) + a2 * (b3 * c1 - b1 * c3) + a3 * (b1 * c2 - b2 * c1); } class GisBSPTree { public: struct Split; struct Node { Node() {} Node(int branch) : branch(branch) {} Node(One split) : branch(-1), split(split) {} int branch; One split; }; struct Split { Split(Pointf n, double c, pick_ Node& minus, pick_ Node& plus) : n(n), c(c), minus(minus), plus(plus) {} Pointf n; double c; // np = c Node minus; // np - c < 0 Node plus; // np - c > 0 }; struct Tree : RefBase { Tree(pick_ Node& root) : root(root) {} Node root; }; public: GisBSPTree() {} GisBSPTree(int branch) : tree(new Tree(Node(branch))) {} GisBSPTree(pick_ Node& root) : tree(new Tree(root)) {} bool IsEmpty() const { return !tree->root.split; } int GetBranch() const { return tree->root.branch; } const Node& GetRoot() const { return tree->root; } private: RefCon tree; }; class ConvertDegree : public Convert { public: ConvertDegree(int decimals = 3, bool not_null = true, double min = -360, double max = +360); virtual ~ConvertDegree(); virtual Value Format(const Value& v) const; virtual Value Scan(const Value& v) const; virtual int Filter(int c) const; ConvertDegree& Decimals(int d) { decimals = d; return *this; } int GetDecimals() const { return decimals; } ConvertDegree& NotNull(bool nn = true) { not_null = nn; return *this; } bool IsNotNull() const { return not_null; } ConvertDegree& MinMax(double l, double h) { min = l; max = h; return *this; } double GetMin() const { return min; } double GetMax() const { return max; } private: int decimals; bool not_null; double min, max; }; class GisFunction { public: virtual ~GisFunction() {} virtual double Get(double x) const = 0; double operator () (double x) const { return Get(x); } void Dump(double xmin, double xmax, int steps) const; }; class GisInverse : public GisFunction { public: GisInverse(double xmin, double xmax, const GisFunction& fn, int sections, double epsilon); double GetXMin() const { return xmin; } double GetXMax() const { return xmin; } double GetYMin() const { return ymin; } double GetYMax() const { return ymax; } virtual double Get(double y) const; private: double xmin, xmax; double ymin, ymax; double rawxmin, rawxmax; double rawymin, rawymax; double xstep, ystep; double epsilon; const GisFunction& fn; Vector ymap; VectorMap accel; }; String GisInverseDelta(double xmin, double xmax, const GisFunction& fn, int sections, double epsilon, int samples); String GisInverseTiming(double xmin, double xmax, const GisFunction& fn, int sections, double epsilon); class GisInterpolator { public: GisInterpolator() {} // Interpolator(Callback2 calc, double xmin, double xmax, int min_depth, int max_depth, double epsilon) // { Create(calc, xmin, xmax, min_depth, max_depth, epsilon); } GisInterpolator(double xmin, double xmax, const GisFunction& fn, int buckets, int sections, int samples) { Create(xmin, xmax, fn, buckets, sections, samples); } void Clear() { bucket_index.Clear(); abc.Clear(); } bool IsEmpty() const { return bucket_index.IsEmpty(); } // void Create(Callback2 calc, double xmin, double xmax, int min_depth, int max_depth, double epsilon); void Create(double xmin, double xmax, const GisFunction& fn, int buckets, int sections, int samples); void CreateInverse(double xmin, double xmax, const GisFunction& fn, int buckets, int sections, int samples); String CreateDump(double xmin, double xmax, const GisFunction& fn, int buckets, int sections, int samples, int check); String CreateInverseDump(double xmin, double xmax, const GisFunction& fn, int buckets, int sections, int samples, int check); String Dump(const GisFunction& fn, int check); double GetXMin() const { return xmin; } double GetXMax() const { return xmax; } double Get(double x) const; double operator () (double x) const { return Get(x); } // double Linear(double x) const; private: /* struct Tree { double mid_y; One left; One right; }; One CreateTree(Callback2 calc, const Rectf& extent, const Pointf& mid, int depth, int min_depth, int max_depth, double epsilon); */ private: struct Bucket : Moveable { int begin, count; double a0, a1, a2; }; double xmin, xmax; double step; int limit; /* Vector index; Vector begin; Vector len; Vector abc; */ // Vector bucket_list; Vector bucket_index; Vector abc; // Rectf extent; // double divisor; // Vector y; // int scale; // One tree; }; String GisInterpolatorDelta(double xmin, double xmax, const GisFunction& fn, int buckets, int sections, int samples, int check); String GisInterpolatorTiming(double xmin, double xmax, const GisFunction& fn, int buckets, int sections, int samples, int check); class GisOrientation { public: GisOrientation(Pointf lonlat_pole = Pointf(0, 90)); Pointf Local(double lon, double lat) const { return (this->*localproc)(lon, lat); } Pointf Local(Pointf lonlat) const { return (this->*localproc)(lonlat.x, lonlat.y); } Rectf LocalExtent(const Rectf& lonlat) const { return (this->*localextent)(lonlat); } Rectf LocalExtent(double l, double t, double r, double b) const { return (this->*localextent)(Rectf(l, t, r, b)); } Pointf Global(double lon, double lat) const { return (this->*globalproc)(lon, lat); } Pointf Global(Pointf lonlat) const { return (this->*globalproc)(lonlat.x, lonlat.y); } Rectf GlobalExtent(const Rectf& lonlat) const { return (this->*globalextent)(lonlat); } Rectf GlobalExtent(double l, double t, double r, double b) const { return (this->*globalextent)(Rectf(l, t, r, b)); } bool IsIdentity() const { return identity; } private: Pointf LocalAny(double lon, double lat) const; Pointf GlobalAny(double lon, double lat) const; Pointf LocalDelta(double lon, double lat) const; Pointf GlobalDelta(double lon, double lat) const; Pointf Identity(double lon, double lat) const; Rectf LocalAnyExtent(const Rectf& lonlat) const; Rectf GlobalAnyExtent(const Rectf& lonlat) const; Rectf LocalDeltaExtent(const Rectf& lonlat) const; Rectf GlobalDeltaExtent(const Rectf& lonlat) const; Rectf IdentityExtent(const Rectf& lonlat) const; private: Pointf (GisOrientation::*localproc)(double lon, double lat) const; Pointf (GisOrientation::*globalproc)(double lon, double lat) const; Rectf (GisOrientation::*localextent)(const Rectf& rc) const; Rectf (GisOrientation::*globalextent)(const Rectf& rc) const; bool identity; Pointf pole; double delta_phi; double suk, cuk; bool sukneg, cukneg; }; class GisEllipsoid { public: GisEllipsoid() : a(0), from_wgs84(Matrixf3_1()) {} static const Index& EnumEPSG(); static GisEllipsoid GetEPSG(int code); static GisEllipsoid AB(double a, double b); static GisEllipsoid AI(double a, double i); static GisEllipsoid AE2(double a, double e2); static GisEllipsoid R(double r); enum { BESSEL_1841 = 7004, HAYFORD_1909 = 7022, KRASSOWSKY_1940 = 7024, WGS_1984 = 7030, }; bool IsNullInstance() const { return !a; } bool IsSphere() const { return b == a; } double M(double phi) const { double t = 1 - e2 * sqr(sin(phi)); return a * a / (b * t * sqrt(t)); } double N(double phi) const { double t = 1 - e2 * sqr(sin(phi)); return a / sqrt(t); } Pointf3 To3D(double lon, double lat, double elev = 0) const; Pointf3 To3D(const Pointf& lonlat, double elev = 0) const { return To3D(lonlat.x, lonlat.y, elev); } Pointf3 To3D(const Pointf3& lonlatelev) const { return To3D(lonlatelev.x, lonlatelev.y, lonlatelev.z); } Pointf From3D(double x, double y, double z) const; Pointf From3D(const Pointf3& xyz) const { return From3D(xyz.x, xyz.y, xyz.z); } public: double a; double b; double e2; double i; Matrixf3 from_wgs84; int epsg_code; String name; String description; String source; }; bool operator == (const GisEllipsoid& ea, const GisEllipsoid& eb); inline bool operator != (const GisEllipsoid& ea, const GisEllipsoid& eb) { return !(ea == eb); } class GisCoords : Moveable { public: enum STYLE { STYLE_EDIT, STYLE_ANGLE, STYLE_DROPLIST, STYLE_OPTION, STYLE_OPTION3, }; struct Arg { Arg() : vtype(ERROR_V), min(Null), max(Null), not_null(true) {} static Arg Edit(double& v, String ident, String name, String help_topic = Null, double min = Null, double max = Null, bool not_null = true); static Arg Angle(double& v, String ident, String name, String help_topic = Null, double min = -2 * M_PI, double max = +2 * M_PI, bool not_null = true); static Arg Edit(String& v, String ident, String name, String help_topic = Null, bool not_null = true); static Arg Edit(Date& d, String ident, String name, String help_topic = Null, bool not_null = true); static Arg Edit(Time& t, String ident, String name, String help_topic = Null, bool not_null = true); static Arg DropList(String& v, String ident, String name, String help_topic, String variants, bool not_null = true); static Arg Option(bool& b, String ident, String name, String help_topic = Null); static Arg Option3(int& b, String ident, String name, String help_topic = Null); Arg& Cond(String ident, Value value) { cond_ident = ident; cond_value = value; return *this; } String ident; String name; String help_topic; int vtype; STYLE style; String variants; String cond_ident; Value cond_value; double min; double max; bool not_null; Ref ref; }; struct ConstArg { ConstArg(String ident, String name, Value value, String help_topic = Null) : ident(ident), name(name), value(value), help_topic(help_topic) {} String ident; String name; Value value; String help_topic; }; class Data : public RefBase { public: Data(); virtual GisCoords DeepCopy() const = 0; virtual int GetBranchCount() const; virtual Array LonLatBoundary(const Rectf& lonlat_extent, int branch) const; virtual GisBSPTree GetBranchTree(const Rectf& lonlat_extent) const; virtual Pointf LonLat(Pointf xy) const = 0; virtual Rectf LonLatExtent(const Rectf& xy_extent) const; Pointf3 LonLat3D(Pointf xy, double elevation = 0) const { return ellipsoid.To3D(LonLat(xy), elevation); } virtual Pointf Project(Pointf lonlat, int branch) const = 0; virtual Rectf ProjectExtent(const Rectf& lonlat_extent) const; Pointf Project3D(Pointf3 xyz, int branch) const { return Project(ellipsoid.From3D(xyz), branch); } virtual double ProjectDeviation(Pointf lonlat1, Pointf lonlat2, int branch) const; virtual double ProjectRatio(Pointf lonlat, int branch) const; virtual double ExtentDeviation(const Rectf& lonlat_extent) const; virtual Sizef MinMaxRatio(const Rectf& lonlat_extent) const; // virtual String ToString() const = 0; virtual Array EnumArgs() = 0; virtual Array EnumConstArgs() const = 0; virtual void SyncArgs() = 0; virtual bool IsProjected() const; bool IsIdentity(const Data *data) const; public: String ident; GisEllipsoid ellipsoid; Rectf lonlat_limits; int epsg_code; String name; String description; String coordsys; }; GisCoords(const Nuller& = Null) {} GisCoords(RefPtr data) : data(data) {} GisCoords(Data *data) : data(data) {} GisCoords(const Value& v) { if(IsTypeRaw(v)) *this = ValueTo(v); } operator Value() const { return RawToValue(*this); } bool IsNullInstance() const { return !data; } bool Equals(const GisCoords& co) const; GisCoords DeepCopy() const { return data->DeepCopy(); } int GetBranchCount() const { return data->GetBranchCount(); } Array LonLatBoundary(const Rectf& lonlat_extent, int branch) const { return data->LonLatBoundary(lonlat_extent, branch); } GisBSPTree GetBranchTree(const Rectf& lonlat_extent) const { return data->GetBranchTree(lonlat_extent); } Pointf LonLat(Pointf xy) const { return data->LonLat(xy); } Rectf LonLatExtent(const Rectf& xy_extent) const { return data->LonLatExtent(xy_extent); } Pointf3 LonLat3D(Pointf xy, double elevation = 0) const { return data->LonLat3D(xy, elevation); } Pointf Project(Pointf lonlat, int branch) const { return data->Project(lonlat, branch); } Rectf ProjectExtent(const Rectf& lonlat_extent) const { return data->ProjectExtent(lonlat_extent); } Pointf Project3D(Pointf3 xyz, int branch) const { return data->Project3D(xyz, branch); } double ProjectDeviation(Pointf lonlat1, Pointf lonlat2, int branch) const { return data->ProjectDeviation(lonlat1, lonlat2, branch); } double ProjectRatio(Pointf lonlat, int branch) const { return data->ProjectRatio(lonlat, branch); } double ExtentDeviation(const Rectf& lonlat_extent) const { return data->ExtentDeviation(lonlat_extent); } Sizef MinMaxRatio(const Rectf& lonlat_extent) const { return data->MinMaxRatio(lonlat_extent); } Rectf LonLatLimits() const { return data->lonlat_limits; } // String ToString() const { return data->ToString(); } String GetIdent() const { return !!data ? data->ident : String::GetVoid(); } int GetEPSGCode() const { return !!data ? data->epsg_code : (int)Null; } String GetName() const { return !!data ? data->name : String::GetVoid(); } String GetDescription() const { return !!data ? data->description : String::GetVoid(); } String GetCoordsys() const { return !!data ? data->coordsys : String::GetVoid(); } Array EnumArgs() { return data->EnumArgs(); } Array EnumConstArgs() const { return data->EnumConstArgs(); } void SyncArgs() { data->SyncArgs(); } bool IsProjected() const { return data->IsProjected(); } bool IsIdentity(GisCoords gp) const { return data->IsIdentity(~gp.data); } const GisEllipsoid& GetEllipsoid() const { return data->ellipsoid; } void SetEllipsoid(const GisEllipsoid& e) { data->ellipsoid = e; } Pointf3 To3D(Pointf lonlat, double elevation = 0) const { return data->ellipsoid.To3D(lonlat, elevation); } Pointf From3D(Pointf3 xyz) const { return data->ellipsoid.From3D(xyz); } const Matrixf3& FromWGS84() const { return data->ellipsoid.from_wgs84; } Data *operator ~ () const { return ~data; } static const Vector& EnumEPSG(); static GisCoords GetEPSG(int code); public: RefPtr data; }; inline bool operator == (const GisCoords& a, const GisCoords& b) { return a.Equals(b); } inline bool operator != (const GisCoords& a, const GisCoords& b) { return !a.Equals(b); } class GisTransform : Moveable { public: class Data : public RefBase { public: virtual ~Data() {} virtual bool IsNullInstance() const { return IsNull(source) && IsNull(target); } virtual GisTransform DeepCopy() const = 0; virtual Pointf Target(Pointf src) const = 0; virtual Pointf Source(Pointf trg) const = 0; virtual Rectf TargetExtent(const Rectf& src) const = 0; virtual Rectf SourceExtent(const Rectf& src) const = 0; virtual double SourceDeviation(Pointf src1, Pointf src2) const = 0; virtual double TargetDeviation(Pointf trg1, Pointf trg2) const = 0; virtual double SourceExtentDeviation(const Rectf& src) const = 0; virtual double TargetExtentDeviation(const Rectf& trg) const = 0; virtual Sizef SourceMinMaxRatio(const Rectf& src) const = 0; virtual Sizef TargetMinMaxRatio(const Rectf& trg) const = 0; virtual GisBSPTree TargetBranchTree(const Rectf& trg) const = 0; virtual GisBSPTree SourceBranchTree(const Rectf& src) const = 0; virtual Rectf TargetLimits() const = 0; virtual Rectf SourceLimits() const = 0; virtual bool IsProjected() const = 0; virtual bool IsIdentity() const = 0; public: GisCoords source; GisCoords target; }; public: GisTransform(const Nuller& = Null); GisTransform(RefPtr data) : data(data) {} GisTransform(Data *data) : data(data) {} GisTransform(GisCoords source, GisCoords target); bool IsNullInstance() const { return data->IsNullInstance(); } GisTransform DeepCopy() const { return data->DeepCopy(); } Pointf Target(Pointf src) const { return data->Target(src); } Pointf Source(Pointf trg) const { return data->Source(trg); } Rectf TargetExtent(const Rectf& src) const { return data->TargetExtent(src); } Rectf SourceExtent(const Rectf& trg) const { return data->SourceExtent(trg); } double SourceDeviation(Pointf src1, Pointf src2) const { return data->SourceDeviation(src1, src2); } double TargetDeviation(Pointf trg1, Pointf trg2) const { return data->TargetDeviation(trg1, trg2); } double SourceExtentDeviation(const Rectf& src) const { return data->SourceExtentDeviation(src); } double TargetExtentDeviation(const Rectf& trg) const { return data->TargetExtentDeviation(trg); } Sizef SourceMinMaxRatio(const Rectf& src) const { return data->SourceMinMaxRatio(src); } Sizef TargetMinMaxRatio(const Rectf& trg) const { return data->TargetMinMaxRatio(trg); } GisBSPTree SourceBranchTree(const Rectf& src) const { return data->SourceBranchTree(src); } GisBSPTree TargetBranchTree(const Rectf& trg) const { return data->TargetBranchTree(trg); } Rectf TargetLimits() const { return data->TargetLimits(); } Rectf SourceLimits() const { return data->SourceLimits(); } bool IsProjected() const { return data->IsProjected(); } bool IsIdentity() const { return data->IsIdentity(); } GisCoords Source() const { return data->source; } GisCoords Target() const { return data->target; } GisTransform Reverse() const { return GisTransform(Target(), Source()); } Data *operator ~ () const { return ~data; } bool Equals(const GisTransform& t) const; public: RefPtr data; }; inline bool operator == (const GisTransform& a, const GisTransform& b) { return a.Equals(b); } inline bool operator != (const GisTransform& a, const GisTransform& b) { return !a.Equals(b); } inline Pointf operator * (Pointf pt, const GisTransform& t) { return t.Target(pt); } inline Rectf operator * (const Rectf& rc, const GisTransform& t) { return t.TargetExtent(rc); } inline Pointf operator / (Pointf pt, const GisTransform& t) { return t.Source(pt); } inline Rectf operator / (const Rectf& rc, const GisTransform& t) { return t.SourceExtent(rc); } struct SegmentTreeInfo { Matrixf img_src; GisTransform src_trg; Matrixf trg_pix; int branch; int max_depth; double max_deviation; bool antialias; }; inline Point operator * (Point pt, const SegmentTreeInfo& sti) { return PointfToPoint(Pointf(pt) * sti.img_src * sti.src_trg * sti.trg_pix); } class LinearSegmentTree { public: struct Node { Point source; Point target; One below; One above; }; public: Point source1; Point source2; Point target1; Point target2; One split; }; LinearSegmentTree CreateLinearTree(Point s1, Point s2, const SegmentTreeInfo& info); class PlanarSegmentTree { public: struct Split; struct Node { Rect source; Point trg_topleft, trg_topright, trg_bottomleft, trg_bottomright; One split; }; struct Split { Node topleft; Node topright; Node bottomleft; Node bottomright; }; public: Node root; }; PlanarSegmentTree CreatePlanarTree(const LinearSegmentTree& left, const LinearSegmentTree& top, const LinearSegmentTree& right, const LinearSegmentTree& bottom, const SegmentTreeInfo& info); END_UPP_NAMESPACE #endif