| 844 | == !GeometryFactory Examples == |
| 845 | |
| 846 | === Elliptical Arc Segment Example === |
| 847 | |
| 848 | {{{ |
| 849 | FdoICurveString* CreateCurveString() |
| 850 | { |
| 851 | // Create and return a curve string consisting of |
| 852 | // one elliptical arc segment |
| 853 | // one linear string segment |
| 854 | |
| 855 | // line segment = (0 0 0), (3 0 0), (3 2 0) |
| 856 | |
| 857 | FdoPtr<FdoFgfGeometryFactory> gf = FdoFgfGeometryFactory::GetInstance(); |
| 858 | |
| 859 | FdoPtr<FdoDirectPositionCollection> points = FdoDirectPositionCollection::Create(); |
| 860 | FdoPtr<FdoIDirectPosition> pt1 = gf->CreatePositionXY(0.0, 0.0); |
| 861 | FdoPtr<FdoIDirectPosition> pt2 = gf->CreatePositionXY(3.0, 0.0); |
| 862 | FdoPtr<FdoIDirectPosition> pt3 = gf->CreatePositionXY(3.0, 2.0); |
| 863 | points->Add(pt1); |
| 864 | points->Add(pt2); |
| 865 | points->Add(pt3); |
| 866 | |
| 867 | FdoPtr<FdoILineStringSegment> lineSeg = gf->CreateLineStringSegment(points); |
| 868 | |
| 869 | // elliptical segment = (3 2 0), (-1 1 0), (1 3 0), (2 0 0), (3 0 0) |
| 870 | |
| 871 | FdoPtr<FdoIDirectPosition> startPos = gf->CreatePositionXY(3.0, 2.0); |
| 872 | FdoPtr<FdoIDirectPosition> midPos = gf->CreatePositionXY(-1.0, 1.0); |
| 873 | FdoPtr<FdoIDirectPosition> endPos = gf->CreatePositionXY(1.0, 3.0); |
| 874 | FdoPtr<FdoIDirectPosition> focalPos1 = gf->CreatePositionXY(2.0, 0.0); |
| 875 | FdoPtr<FdoIDirectPosition> focalPos2 = gf->CreatePositionXY(3.0, 0.0); |
| 876 | |
| 877 | FdoPtr<FdoIEllipticalArcSegment> arcSeg = gf->CreateEllipticalArcSegment( |
| 878 | startPos, |
| 879 | midPos, |
| 880 | endPos, |
| 881 | focalPos1, |
| 882 | focalPos2); |
| 883 | |
| 884 | FdoPtr<FdoCurveSegmentCollection> curveSegs = FdoCurveSegmentCollection::Create(); |
| 885 | curveSegs->Add(lineSeg); |
| 886 | curveSegs->Add(arcSeg); |
| 887 | |
| 888 | FdoPtr<FdoICurveString> curveString = gf->CreateCurveString(curveSegs); |
| 889 | |
| 890 | CheckFGFT(curveString, L"CURVESTRING (0 0 (" |
| 891 | L"LINESTRINGSEGMENT (3 0, 3 2)," |
| 892 | L"ELLIPTICALARCSEGMENT (-1 1, 1 3, 2 0, 3, 0)" |
| 893 | L"))"); |
| 894 | |
| 895 | return FDO_SAFE_ADDREF(curveString.p); |
| 896 | } |
| 897 | }}} |
| 898 | |
| 899 | === Circle Segment Example === |
| 900 | |
| 901 | {{{ |
| 902 | FdoICurveString* CreateCurveString() |
| 903 | { |
| 904 | // Create and return a curve string consisting of |
| 905 | // one circle segment |
| 906 | |
| 907 | // circle segment = (0 0 0), (-1 1 0), (1 3 0) |
| 908 | |
| 909 | FdoPtr<FdoIDirectPosition> pt1 = gf->CreatePositionXY(0.0, 0.0); |
| 910 | FdoPtr<FdoIDirectPosition> pt2 = gf->CreatePositionXY(-1.0, 1.0); |
| 911 | FdoPtr<FdoIDirectPosition> pt3 = gf->CreatePositionXY(1.0, 3.0); |
| 912 | |
| 913 | FdoPtr<FdoICircleSegment> circleSeg = gf->CreateCircleSegment( |
| 914 | pt1, |
| 915 | pt2, |
| 916 | pt3); |
| 917 | |
| 918 | FdoPtr<FdoCurveSegmentCollection> curveSegs = FdoCurveSegmentCollection::Create(); |
| 919 | curveSegs->Add(circleSeg); |
| 920 | |
| 921 | FdoPtr<FdoICurveString> curveString = gf->CreateCurveString(curveSegs); |
| 922 | |
| 923 | CheckFGFT(curveString, L"CURVESTRING (0 0 (" |
| 924 | L"CIRCLESEGMENT (-1 1, 1 3)" |
| 925 | L"))"); |
| 926 | |
| 927 | return FDO_SAFE_ADDREF(curveString.p); |
| 928 | } |
| 929 | }}} |
| 930 | |
| 931 | === Cubic Spline Segment Example === |
| 932 | |
| 933 | {{{ |
| 934 | FdoICurveString* CreateCurveString() |
| 935 | { |
| 936 | // Create and return a curve string consisting of: |
| 937 | // one linear string segment |
| 938 | // one circular arc segment |
| 939 | // one cubic spline segment |
| 940 | |
| 941 | // line segment = (0 0 0), (7.5 0 0), (11.5 4 0) |
| 942 | |
| 943 | FdoPtr<FdoFgfGeometryFactory> gf = FdoFgfGeometryFactory::GetInstance(); |
| 944 | |
| 945 | FdoPtr<FdoDirectPositionCollection> points = FdoDirectPositionCollection::Create(); |
| 946 | FdoPtr<FdoIDirectPosition> pt1 = gf->CreatePositionXY(0.0, 0.0); |
| 947 | FdoPtr<FdoIDirectPosition> pt2 = gf->CreatePositionXY(7.5, 0.0); |
| 948 | FdoPtr<FdoIDirectPosition> pt3 = gf->CreatePositionXY(11.5, 4.0); |
| 949 | points->Add(pt1); |
| 950 | points->Add(pt2); |
| 951 | points->Add(pt3); |
| 952 | |
| 953 | FdoPtr<FdoILineStringSegment> lineSeg = gf->CreateLineStringSegment(points); |
| 954 | |
| 955 | // circular arc segment = (11.5 4 0), (13 7.5 0), (12.5 12 0) |
| 956 | |
| 957 | FdoPtr<FdoIDirectPosition> startPos = gf->CreatePositionXY(11.5, 4.0); |
| 958 | FdoPtr<FdoIDirectPosition> midPos = gf->CreatePositionXY(13.0, 7.5); |
| 959 | FdoPtr<FdoIDirectPosition> endPos = gf->CreatePositionXY(12.5, 12.0); |
| 960 | |
| 961 | FdoPtr<FdoICircularArcSegment> arcSeg = gf->CreateCircularArcSegment( |
| 962 | startPos, midPos, endPos); |
| 963 | |
| 964 | // cubic spline segment = (8 3 0), (5 15 0), (6 19 0), (0 0 0), (0 0 0) |
| 965 | |
| 966 | FdoPtr<FdoDirectPositionCollection> cntrlptColl = FdoDirectPositionCollection::Create(); |
| 967 | FdoPtr<FdoIDirectPosition> cntrlpt1 = gf->CreatePositionXY(8.0, 3.0); |
| 968 | FdoPtr<FdoIDirectPosition> cntrlpt2 = gf->CreatePositionXY(5.0, 15.0); |
| 969 | FdoPtr<FdoIDirectPosition> cntrlpt3 = gf->CreatePositionXY(6.0, 19.0); |
| 970 | cntrlptColl-Add(cntrlpt1); |
| 971 | cntrlptColl-Add(cntrlpt2); |
| 972 | cntrlptColl-Add(cntrlpt3); |
| 973 | |
| 974 | FdoPtr<FdoIDirectPosition> startTan = gf->CreatePositionXY(0.0, 0.0); |
| 975 | FdoPtr<FdoIDirectPosition> endTan = gf->CreatePositionXY(0.0, 0.0); |
| 976 | |
| 977 | FdoPtr<FdoICubicSplineSegment> splineSeg = gf->CreateCubicSplineSegment( |
| 978 | cntrlptColl, |
| 979 | startTan, |
| 980 | endTan); |
| 981 | |
| 982 | FdoPtr<FdoCurveSegmentCollection> curveSegs = FdoCurveSegmentCollection::Create(); |
| 983 | curveSegs->Add(lineSeg); |
| 984 | curveSegs->Add(arcSeg); |
| 985 | curveSegs->Add(splineSeg); |
| 986 | |
| 987 | FdoPtr<FdoICurveString> curveString = gf->CreateCurveString(curveSegs); |
| 988 | |
| 989 | CheckFGFT(curveString, L"CURVESTRING XYZ (0 0 0 (" |
| 990 | L"LINESTRINGSEGMENT (7.5 0 0, 11.5 4 0)," |
| 991 | L"CIRCULARARCSEGMENT (13 7.5 0, 12.5 12 0)," |
| 992 | L"CUBICSPLINESEGMENT (2, 5 15 0, 6 19 0, 0 0 0, 0 0 0)" |
| 993 | L"))" |
| 994 | |
| 995 | return FDO_SAFE_ADDREF(curveString.p); |
| 996 | } |
| 997 | }}} |
| 998 | |
| 999 | == Appendix A: Existing FDO API Curve Segment Classes == |
| 1000 | |
| 1001 | The classes described in the following sections currently exist in the FDO Geometry API (Version 3.6.0) and form base and sibling classes to those proposed in the sections above. They are included here for illustrative and comparative purposes. |
| 1002 | |
| 1003 | === ICurveSegmentAbstract === |
| 1004 | |
| 1005 | {{{ |
| 1006 | /// \brief |
| 1007 | /// The FdoICurveSegmentAbstract class is an abstract geometric Curve Segment object. |
| 1008 | /// This class is used strictly as a component of curves |
| 1009 | /// and, thus, does not inherit from IGeometry. |
| 1010 | class FdoICurveSegmentAbstract : public FdoIDisposable |
| 1011 | { |
| 1012 | public: |
| 1013 | |
| 1014 | /// \brief |
| 1015 | /// Gets the envelope for the curve segment. |
| 1016 | /// |
| 1017 | /// \return |
| 1018 | /// Returns the envelope |
| 1019 | /// |
| 1020 | FDO_GEOM_API virtual FdoIEnvelope* GetEnvelope() const = 0; |
| 1021 | |
| 1022 | /// \brief |
| 1023 | /// Gets the starting position of this curve segment. |
| 1024 | /// |
| 1025 | /// \return |
| 1026 | /// Returns the starting position |
| 1027 | /// |
| 1028 | FDO_GEOM_API virtual FdoIDirectPosition* GetStartPosition() const = 0; |
| 1029 | |
| 1030 | /// \brief |
| 1031 | /// Gets the ending position of this curve segment. |
| 1032 | /// |
| 1033 | /// \return |
| 1034 | /// Returns the ending position |
| 1035 | /// |
| 1036 | FDO_GEOM_API virtual FdoIDirectPosition* GetEndPosition() const = 0; |
| 1037 | |
| 1038 | /// \brief |
| 1039 | /// Gets the closure state for the curve segment. |
| 1040 | /// |
| 1041 | /// \remarks |
| 1042 | /// The meaning behind this method is not guaranteed |
| 1043 | /// to be uniform between derived types or between implementations |
| 1044 | /// of this package. It may represent a computed value, an explicit |
| 1045 | /// attribute, or be true by definition. As a computed value, the |
| 1046 | /// result is typically from simply testing the starting and |
| 1047 | /// ending positions for exact equality. This is only reliable in floating |
| 1048 | /// point arithmetic if these data have identical origins. |
| 1049 | /// As an explicit attribute, it would be persisted with the Geometry and |
| 1050 | /// typically denoted by a parameter in the relevant factory method. |
| 1051 | /// Some Geometry types are closed by definition. |
| 1052 | /// |
| 1053 | /// \return |
| 1054 | /// Returns 'true' if the curve is closed, and false otherwise |
| 1055 | /// |
| 1056 | FDO_GEOM_API virtual bool GetIsClosed() const = 0; |
| 1057 | |
| 1058 | /// \brief |
| 1059 | /// Gets the type of the most-derived interface |
| 1060 | /// in the Geometry package for this object |
| 1061 | /// |
| 1062 | /// \return |
| 1063 | /// Returns the derived type |
| 1064 | /// |
| 1065 | FDO_GEOM_API virtual FdoGeometryComponentType GetDerivedType() const = 0; |
| 1066 | |
| 1067 | /// \brief |
| 1068 | /// Gets the dimensionality of ordinates in this object. |
| 1069 | /// |
| 1070 | /// \remarks |
| 1071 | /// Values are from the FdoDimensionality enumeration. |
| 1072 | /// A return type of "FdoInt32" is used instead of the enumeration, |
| 1073 | /// catering to typical use with bit masking. |
| 1074 | /// |
| 1075 | /// \return |
| 1076 | /// Returns the ordinate dimensionality |
| 1077 | /// |
| 1078 | FDO_GEOM_API virtual FdoInt32 GetDimensionality() const = 0; |
| 1079 | }; |
| 1080 | }}} |
| 1081 | |
| 1082 | === IArcSegmentAbstract === |
| 1083 | |
| 1084 | {{{ |
| 1085 | /// \brief |
| 1086 | /// The FdoIArcSegmentAbstract class is an arc curve segment (abstract) |
| 1087 | class FdoIArcSegmentAbstract : public FdoICurveSegmentAbstract |
| 1088 | { |
| 1089 | public: |
| 1090 | /// \brief |
| 1091 | /// Gets some position along the curve, between the starting and ending positions. |
| 1092 | /// |
| 1093 | /// \remarks |
| 1094 | /// Depending on the derived type and its implementation, this may be a |
| 1095 | /// computed value, or a persisted value used as part |
| 1096 | /// of the definition of the curve segment. This position is the only |
| 1097 | /// means to deduce the curve segment's orientation in some cases, such as |
| 1098 | /// when it is closed or vertically aligned ('on edge' when looking along |
| 1099 | /// the Z axis). |
| 1100 | /// |
| 1101 | /// \return |
| 1102 | /// Returns a midpoint on the curve |
| 1103 | /// |
| 1104 | FDO_GEOM_API virtual FdoIDirectPosition* GetMidPoint() const = 0; |
| 1105 | }; |
| 1106 | }}} |
| 1107 | |
| 1108 | === ICircularArcSegment === |
| 1109 | |
| 1110 | {{{ |
| 1111 | /// \brief |
| 1112 | /// The FdoICircularArcSegment class is a circular arc curve segment |
| 1113 | class FdoICircularArcSegment : public FdoIArcSegmentAbstract |
| 1114 | { |
| 1115 | protected: |
| 1116 | /// \brief |
| 1117 | /// Default destructor. |
| 1118 | /// |
| 1119 | /// \return |
| 1120 | /// Returns nothing |
| 1121 | /// |
| 1122 | FDO_GEOM_API virtual ~FdoICircularArcSegment() {}; |
| 1123 | }; |
| 1124 | }}} |
| 1125 | |
| 1126 | === ILineStringSegment === |
| 1127 | |
| 1128 | {{{ |
| 1129 | /// \brief |
| 1130 | /// The FdoILineStringSegment class is a LineString curve segment type. |
| 1131 | /// The shape of FdoILineStringSegment is the set of positions defined |
| 1132 | /// by the contained collection, plus linear interpolation between |
| 1133 | /// consecutive points. This is a helper type for Geometries in the |
| 1134 | /// Geometry package. |
| 1135 | /// |
| 1136 | /// \remarks |
| 1137 | /// It does not derive from IGeometry. |
| 1138 | /// |
| 1139 | class FdoILineStringSegment : public FdoICurveSegmentAbstract |
| 1140 | { |
| 1141 | public: |
| 1142 | /// \brief |
| 1143 | /// Gets the number of positions in this object. |
| 1144 | /// |
| 1145 | /// \return |
| 1146 | /// Returns the number of positions |
| 1147 | /// |
| 1148 | FDO_GEOM_API virtual FdoInt32 GetCount() const = 0; |
| 1149 | |
| 1150 | /// \brief |
| 1151 | /// Gets the position at the specified (zero-based) index. |
| 1152 | /// |
| 1153 | /// \return |
| 1154 | /// Returns the position |
| 1155 | /// |
| 1156 | FDO_GEOM_API virtual FdoIDirectPosition* GetItem(FdoInt32 index) const = 0; |
| 1157 | |
| 1158 | /// \brief |
| 1159 | /// Gets a collection of all of the positions in this object. |
| 1160 | /// |
| 1161 | /// \return |
| 1162 | /// Returns the positions |
| 1163 | /// |
| 1164 | FDO_GEOM_API virtual FdoDirectPositionCollection* GetPositions() = 0; |
| 1165 | |
| 1166 | /// \brief |
| 1167 | /// Gets the ordinates as an array. |
| 1168 | /// |
| 1169 | /// \remarks |
| 1170 | /// The caller must not free the returned array. |
| 1171 | /// The ordinates are in the order XYZMXYZM..., with only those present |
| 1172 | /// according to the dimensionality. |
| 1173 | /// |
| 1174 | /// \return |
| 1175 | /// Returns the ordinates |
| 1176 | /// |
| 1177 | FDO_GEOM_API virtual const double * GetOrdinates() = 0; |
| 1178 | }; |
| 1179 | }}} |
| 1180 | |
| 1181 | == Appendix B: Questions and Answers == |
| 1182 | |
| 1183 | == ICircleSegment vs. ICircle == |
| 1184 | |
| 1185 | Question: |
| 1186 | |
| 1187 | What if we change the proposal to derive FdoICircleSegment directly from FdoICurveAbstract, in the process renaming FdoICircleSegment to be FdoICircle. To me, this has some merit, since as currently described, a circle must be closed and cannot be combined with any other ArcSegment Types to form complex curve strings. They can only stand alone, and wrapping it in a CurveString seems wasteful. If a user wished to define a non-closed circle, they would use ICircularArcSegment. |
| 1188 | |
| 1189 | Response: |
| 1190 | |
| 1191 | The FdoICircle may be something of a hard sell. In OGC, Circle extends Arc, which extends ArcString, which extends CurveSegment, which implements GenericCurve. |
| 1192 | |
| 1193 | == Can ICircularArcSegment Describe a Closed Circle == |
| 1194 | |
| 1195 | Question: |
| 1196 | |
| 1197 | I’m not sure how CircularArcSegment can describe a full circle. if the start and end points are identical, then you only have two points (start/end and mid-point), which does not define the plane of the arc for XYZ dimensionality. |
| 1198 | |
| 1199 | Response: |
| 1200 | |
| 1201 | For the rest of this explanation, it’s assumed that the circle is complete (start and end are same position). |
| 1202 | |
| 1203 | Take the line that is formed by the start and mid positions. The normal to that line in the XY plane forms another line through the circle to orient it. The circle is treated as if you simply tilted it out of the XY plane by grabbing the mid position. |
| 1204 | |
| 1205 | There is a position of ambiguity: if the circle is standing perfectly on edge so that the start and mid positions coincide in XY (but have different Z). |
| 1206 | |
| 1207 | This (using an FDO circle in 3D) works for round-tripping and a few special functions such as tessellation. However, there are several weak points in Map that assume circular arcs to be in the XY plane. These should be addressed by the time that we add support for more geometry types, assuming that 3D support will be required for all of them. |
| 1208 | |
| 1209 | |