Oracle Spatial中SDO_Geometry详细说明
目录
Oracle中SDO_GEOMETRY数据类型是一个很有威力的结构。你可以用这个类型存储点、线串、多边形、面和立方体等几何体,同样还可以存储这些几何体的同构或异构集合。SDO_GEOMETRY中的SDO_GTYPE属性指定几何体类型(形状),SDO_ELEM_INFO属性和SDO_ORDINATES属性一起指定了几何体的坐标信息和连通性。SDO_POINT属性存储二维或三维的点的位置。简而言之,你可以将OGC简单特性规范12中提到的任何二维类型以及OGC GML 2.0和3.0规范中提到的大多数三维类型(不包括参数曲线和参数面)存储为一个SDO_GEOMETRY。
除了几何结构外,你可以用合适的坐标系将空间参照和SDO_GEOMETRY对象相关联。如果坐标系是基于EPSG模型的,你可以在不同坐标系之间定义自己的转换路径。
SDO_GEOMETRY类型、属性和值
下面是SDO_GEOMETRY每个属性的用处:
SDO_GTYPE属性,表示几何体实际形状的类型(点、线串、多边形、集合、多重点、多重线串或者多重多边形)。尽管SDO_GTYPE属性表示几何体的类型,但它并不指定实际的坐标。
SDO_SRID属性,指定空间参考系(坐标系)的ID。几何体的位置和形状都在该参考系中确定。
如果几何体是一个点(如客户的位置),你可以把它的坐标存储到SDO_GEOMETRY的SDO_POINT属性中。
如果几何体是一个任意形状(如街区网络或城市边界),则可以把它的坐标存储到SDO_ORDINATES和SDO_ELEM_INFO数组属性:
SDO_ORDINATES属性存储所有几何体元素的坐标。
SDO_ELEM_INFO规定在SDO_ORDINATES数组中,一个新的元素从什么地方开始,怎么连接(通过直线还是弧),是点(推荐用SDO_POINT来存储和表示点,)、线串还是多边形。
下面进一步介绍这些属性。
SDO_GTYPE属性
SDO_GTYPE是一个4位的数字,结构为D00T。第一位和最后一位根据几何体的维数和形状采用不同的值,如表4-1所示。第二位和第三位通常被设成0。
下面就是D=2的二维几何类型,SDO_GTYPE参数值具体,如图:
对于一个给定的层,所有的地理对象必须都是相同的维度,不能将二维与三维的数据放在一个层里。
Oracle默认为二维的数据图层,若表示三维的数据图层,需向USER_SDO_GEOM_METADATA的DIMINFO插入X、Y、Z空间索引范围。
SDO_SRID属性
SDO_SRID定义了空间坐标参考系统。如果SDO_SRID为null,则没有指定坐标系统,如果SDO_SRID不为null,那么它的值必须在在MDSYS.CS_SRS 表中的 SRID 列有对应的值,而且它的值必须插入USER_SDO_GEOM_METADATA视图中。
查询srid
具体描述信息
SDO_POINT属性
SDO_POINT_TYPE数据类型:
SDO_GTYPE:格式是D00T,对二维点来说D为2,T为1。
SDO_SRID:它被设置为8307。
SDO_POINT:这个例子中的x,y坐标被设置为SDO_POINT_TYPE类型(-79,37)。z轴为NULL。
SDO_ELEM_INFO:没有被使用,设为NULL。
SDO_ORDINATES:没有被使用,设为NULL。
构造为:SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE(79, 37, NULL), NULL, NULL)
SDO_ELEM_INFO属性
SDO_ELEM_INFO类型的构造方法为:sdo_elem_info_array(a,b.c),其中a,b.c为Number类型。
SDO_ELEM_INFO是理解和掌握SDO_Geometry的重点和难点,SDO_ELEM_INFO 定义了如何理解SDO_ORDINATES中的坐标字符串属性。
SDO_ELEM_INFO每三个数字组合为一个SDO_ELEM_INFO属性单元(具体可以结合下面的例子理解)。
每个SDO_ELEM_INFO属性单元由:SDO_STARTING_OFFSET、SDO_ETYPE 和SDO_INTERPRETATION 组成。下面介绍一下这三个数字的具体含义:
SDO_STARTING_OFFSET:声明了组成当前几何片段的第一个坐标在SDO_ORDINATES数组中的坐标序号。坐标序号是从1开始起算的而非从0开始。这里的SDO_ORDINATES就是sdo_geometry 中的坐标序列,坐标序列是已逗号隔开的数字,具体的计算如:sdo_ordinate_array(1,4,6,7,8,9)中如果以’6’开始几何片段的话,坐标序号SDO_STARTING_OFFSET=3。(具体参考下面的例子理解)
SDO_ETYPE :声明元素的类型。可结合 SDO_STARTING_OFFSET和SDO_ETYPE 表来理解.
SDO_ETYPE 值 = 1, 2, 1003,或2003,说明几何为简单的几何类型。可以全部按SDO_ELEM_INFO 属性单元【即三个以逗号隔开的数】来理解sdo_ordinate_array中的坐标序列。
特别说明:SDO_ETYPE 值 = 1003 ,假如几何类型为面,则表示为外多边形环(以逆时针顺序)
SDO_ETYPE 值 = 2003 ,假如几何类型为面,则表示为内多边形环(以顺时针顺序)
SDO_ETYPE 值 = 4,1005或2005,说明几何为组合元素,往往第一个三数字组不是SDO_ELEM_INFO 属性单元,而是为了说明组合元素的信息。具体可以参见下面 复杂多义线 和 复杂多边形 的例子。
SDO_INTERPRETATION:有两种可能的意思,依赖地SDO_ETYPE是否是组合元素。如果SDO_ETYPE 值 = 4,1005或2005,标识的是有多少组合部分,具体参考 复杂多义线 和 复杂多边形 的例子。如果SDO_ETYPE 值 = 1, 2, 1003,或2003,标识决定了元素坐标队列的翻译顺序。
SDO_STARTING_OFFSET和SDO_ETYPE 表 如下图:
SDO_ORDINATES属性
SDO_ORDINATES类型的构造方法为:sdo_ordinate_array(x1,y1,x2,y2,……),其中x1,y1类型等为Double和Int都可。
SDO_ORDINATES存储的是空间对象的几何节点坐标序列,用逗号将X、Y、Z以及不同点之间隔开,该字段性质:长度=1048576的数字Number类型。如果几何为二维的情况,存储的序列为{Y1, X2, Y2, X3, Y3, X4, Y4……}格式;几何为三维坐标的话,如三维坐标的多边形它的存储的序列为{X1, Y1, Z1, X2, Y2, Z2, X3, Y3, Z3, X4, Y4, Z4, X1, Y1, Z1}格式。坐标序列中的数据必须都合法且不为空。具体坐标的组合成几何的结合SDO_ELEM_INFO来理解。
例子
该几何体的构造函数如下所示:
SDO_GEOMETRY
(
2002,32774,null,
SDO_ELEM_INFO_ARRAY(1,2,2),
SDO_ORDINATE_ARRAY(Xa,Ya, Xb,Yb, Xc,Yc, Xd,Yd, Xe,Ye)
)
SQL> INSERT INTO geometry_examples (name, description, geom) VALUES
(
‘3-D Composite Surface’,
‘3-dimensional Composite with 2 rectangle polygons ‘,
SDO_GEOMETRY
(
3003, – SDO_GTYPE format: D00T. Set to
3003 for a 3-dimensional Surface
NULL, – No coordinate system
NULL, – No data in SDO_POINT attribute
SDO_ELEM_INFO_ARRAY(
1, – Offset of composite element
1006, – Etype for composite surface element
2, – Number of composing polygons
1, – Offset for ordinates in SDO_ORDINATE_ARRAY
1003, – Etype for Exterior (outer) ring of FIRST polygon
3, – Polygon is an axis-aligned rectangle
7, – Offset for second exterior polygon
1003, – Etype for exterior Ring of SECOND polygon
3 – Polygon is an axis-aligned rectangle
),
SDO_ORDINATE_ARRAY
(
2, 0,2, – min-corner for exterior ring of first polygon,
4,2,2, – max-corner for exterior ring of first polygon
2,0, 2, – min-corner for second element rectangle
4,0,4 – max-corner for second element rectangle
)
)
);
立方体下一步解释。
附:自己整理了sdogeometry与gdal对象互相转换(c++代码)
//sdogeometry ->OGRGeometry
SS_CLASS_EXPORT OGRGeometry* TranslateGeometry( SSDataBase::SSDBSDOGeometry* pSdoGeometry );
//OGRGeometry ->SDOGeometry
SS_CLASS_EXPORT SSDataBase::SSDBSDOGeometry* TranslateToSDOGeometry( OGRGeometry * poGeometry, int *pnGType );
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool OGROCIStrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY,
double dfRadius,
double dfStartAngle, double dfEndAngle,
double dfMaxAngleStepSizeDegrees,
OGRLineString *poLine )
{
double dfArcX, dfArcY, dfSlice;
int iPoint, iAppendLocation, nVertexCount;
double dfEps = dfRadius / 100000.0;
nVertexCount = (int)
ceil(fabs(dfEndAngle - dfStartAngle)/dfMaxAngleStepSizeDegrees) + 1;
nVertexCount = MAX(2,nVertexCount);
dfSlice = (dfEndAngle-dfStartAngle)/(nVertexCount-1);
for( iPoint=0; iPoint < nVertexCount; iPoint++ )
{
double dfAngle;
dfAngle = (dfStartAngle + iPoint * dfSlice) * PI / 180.0;
dfArcX = dfCenterX + cos(dfAngle) * dfRadius;
dfArcY = dfCenterY + sin(dfAngle) * dfRadius;
if( iPoint == 0 )
{
iAppendLocation = poLine->getNumPoints();
if( poLine->getNumPoints() > 0
&& fabs(poLine->getX(poLine->getNumPoints()-1)-dfArcX) < dfEps
&& fabs(poLine->getY(poLine->getNumPoints()-1)-dfArcY) < dfEps)
{
poLine->setNumPoints(
poLine->getNumPoints() + nVertexCount - 1 );
}
else
{
poLine->setNumPoints(
poLine->getNumPoints() + nVertexCount - 1 );
poLine->setPoint( iAppendLocation++, dfArcX, dfArcY );
}
}
else
poLine->setPoint( iAppendLocation++, dfArcX, dfArcY );
}
return true;
}
bool OGROCIArcCenterFromEdgePoints( double x_c0, double y_c0,
double x_c1, double y_c1,
double x_c2, double y_c2,
double *x_center, double *y_center )
{
/* -------------------------------------------------------------------- */
/* Handle a degenerate case that occurs in OSNI products by */
/* making some assumptions. If the first and third points are */
/* the same assume they are intended to define a full circle, */
/* and that the second point is on the opposite side of the */
/* circle. */
/* -------------------------------------------------------------------- */
if( x_c0 == x_c2 && y_c0 == y_c2 )
{
*x_center = (x_c0 + x_c1) * 0.5;
*y_center = (y_c0 + y_c1) * 0.5;
return true;
}
/* -------------------------------------------------------------------- */
/* Compute the inverse of the slopes connecting the first and */
/* second points. Also compute the center point of the two */
/* lines ... the point our crossing line will go through. */
/* -------------------------------------------------------------------- */
double m1, x1, y1;
if( (y_c1 - y_c0) != 0.0 )
m1 = (x_c0 - x_c1) / (y_c1 - y_c0);
else
m1 = 1e+10;
x1 = (x_c0 + x_c1) * 0.5;
y1 = (y_c0 + y_c1) * 0.5;
/* -------------------------------------------------------------------- */
/* Compute the same for the second point compared to the third */
/* point. */
/* -------------------------------------------------------------------- */
double m2, x2, y2;
if( (y_c2 - y_c1) != 0.0 )
m2 = (x_c1 - x_c2) / (y_c2 - y_c1);
else
m2 = 1e+10;
x2 = (x_c1 + x_c2) * 0.5;
y2 = (y_c1 + y_c2) * 0.5;
/* -------------------------------------------------------------------- */
/* Turn these into the Ax+By+C = 0 form of the lines. */
/* -------------------------------------------------------------------- */
double a1, a2, b1, b2, c1, c2;
a1 = m1;
a2 = m2;
b1 = -1.0;
b2 = -1.0;
c1 = (y1 - m1*x1);
c2 = (y2 - m2*x2);
/* -------------------------------------------------------------------- */
/* Compute the intersection of the two lines through the center */
/* of the circle, using Kramers rule. */
/* -------------------------------------------------------------------- */
double det_inv;
if( a1*b2 - a2*b1 == 0.0 )
return false;
det_inv = 1 / (a1*b2 - a2*b1);
*x_center = (b1*c2 - b2*c1) * det_inv;
*y_center = (a2*c1 - a1*c2) * det_inv;
return true;
}
bool OGROCIStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
double dfAlongX, double dfAlongY,
double dfEndX, double dfEndY,
double dfMaxAngleStepSizeDegrees,
int bForceWholeCircle,
OGRLineString *poLine )
{
double dfStartAngle, dfEndAngle, dfAlongAngle;
double dfCenterX, dfCenterY, dfRadius;
if( !OGROCIArcCenterFromEdgePoints( dfStartX, dfStartY,
dfAlongX, dfAlongY,
dfEndX, dfEndY,
&dfCenterX, &dfCenterY ) )
return false;
if( bForceWholeCircle || (dfStartX == dfEndX && dfStartY == dfEndY) )
{
dfStartAngle = 0.0;
dfEndAngle = 360.0;
}
else
{
double dfDeltaX, dfDeltaY;
dfDeltaX = dfStartX - dfCenterX;
dfDeltaY = dfStartY - dfCenterY;
dfStartAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
dfDeltaX = dfAlongX - dfCenterX;
dfDeltaY = dfAlongY - dfCenterY;
dfAlongAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
dfDeltaX = dfEndX - dfCenterX;
dfDeltaY = dfEndY - dfCenterY;
dfEndAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
// Try positive (clockwise?) winding.
while( dfAlongAngle < dfStartAngle )
dfAlongAngle += 360.0;
while( dfEndAngle < dfAlongAngle )
dfEndAngle += 360.0;
// If that doesn't work out, then go anticlockwise.
if( dfEndAngle - dfStartAngle > 360.0 )
{
while( dfAlongAngle > dfStartAngle )
dfAlongAngle -= 360.0;
while( dfEndAngle > dfAlongAngle )
dfEndAngle -= 360.0;
}
}
dfRadius = sqrt( (dfCenterX - dfStartX) * (dfCenterX - dfStartX)
+ (dfCenterY - dfStartY) * (dfCenterY - dfStartY) );
bool bResult;
bResult =
OGROCIStrokeArcToOGRGeometry_Angles( dfCenterX, dfCenterY,
dfRadius,
dfStartAngle, dfEndAngle,
dfMaxAngleStepSizeDegrees,
poLine );
/* -------------------------------------------------------------------- */
/* Force the points for arcs, to avoid odd rounding/math */
/* issues. Perhaps we should do this for the start too, but */
/* this is a bit tricky since it isn't obvious which point is */
/* the start. */
/* -------------------------------------------------------------------- */
if( bResult && !bForceWholeCircle )
{
poLine->setPoint( poLine->getNumPoints() - 1,
dfEndX, dfEndY );
}
return bResult;
}
//获取点列坐标
bool GetOrdinalPoint( int iOrdinal, int nDimension,double pdfX, double *pdfY, double *pdfZ, SSDataBase::SSGeomData pSSGeomData )
{
*pdfX = pSSGeomData->GetOrdinates()->at( iOrdinal );
*pdfY = pSSGeomData->GetOrdinates()->at( iOrdinal + 1);
if( nDimension == 3 )
*pdfZ = pSSGeomData->GetOrdinates()->at( iOrdinal + 2 );
return true;
}
//根据elementinfo转换到Geometry
OGRGeometry * TranslateGeometryElement( int *piElement, int nGType, int nDimension,int nEType, int nInterpretation,
int nStartOrdinal, int nElemOrdCount, SSDataBase::SSGeomData* pSSGeomData )
{
/* ——————————————————————– */
/* Handle simple point. */
/* ——————————————————————– */
if( nEType == 1 && nInterpretation == 1 )
{
OGRPoint *poPoint = new OGRPoint();
double dfX, dfY, dfZ = 0.0;
GetOrdinalPoint( nStartOrdinal, nDimension, &dfX, &dfY, &dfZ, pSSGeomData );
poPoint->setX( dfX );
poPoint->setY( dfY );
if( nDimension == 3 )
poPoint->setZ( dfZ );
return poPoint;
}
/* -------------------------------------------------------------------- */
/* Handle multipoint. */
/* -------------------------------------------------------------------- */
else if( nEType == 1 && nInterpretation > 1 )
{
OGRMultiPoint *poMP = new OGRMultiPoint();
double dfX, dfY, dfZ = 0.0;
int i;
assert( nInterpretation == nElemOrdCount / nDimension );
for( i = 0; i < nInterpretation; i++ )
{
GetOrdinalPoint( nStartOrdinal + i*nDimension, nDimension,
&dfX, &dfY, &dfZ, pSSGeomData );
OGRPoint *poPoint = (nDimension == 3) ? new OGRPoint( dfX, dfY, dfZ ): new OGRPoint( dfX, dfY );
poMP->addGeometryDirectly( poPoint );
}
return poMP;
}
/* -------------------------------------------------------------------- */
/* Discard orientations for oriented points. */
/* -------------------------------------------------------------------- */
else if( nEType == 1 && nInterpretation == 0 )
{
return NULL;
}
/* -------------------------------------------------------------------- */
/* Handle line strings consisting of straight segments. */
/* -------------------------------------------------------------------- */
else if( nEType == 2 && nInterpretation == 1 )
{
OGRLineString *poLS = new OGRLineString();
int nPointCount = nElemOrdCount / nDimension, i;
poLS->setNumPoints( nPointCount );
for( i = 0; i < nPointCount; i++ )
{
double dfX, dfY, dfZ = 0.0;
GetOrdinalPoint( i*nDimension + nStartOrdinal, nDimension,
&dfX, &dfY, &dfZ, pSSGeomData );
if (nDimension == 3)
poLS->setPoint( i, dfX, dfY, dfZ );
else
poLS->setPoint( i, dfX, dfY );
}
return poLS;
}
/* -------------------------------------------------------------------- */
/* Handle line strings consisting of circular arcs. */
/* -------------------------------------------------------------------- */
else if( nEType == 2 && nInterpretation == 2 )
{
OGRLineString *poLS = new OGRLineString();
int nPointCount = nElemOrdCount / nDimension, i;
for( i = 0; i < nPointCount-2; i += 2 )
{
double dfStartX, dfStartY, dfStartZ = 0.0;
double dfMidX, dfMidY, dfMidZ = 0.0;
double dfEndX, dfEndY, dfEndZ = 0.0;
GetOrdinalPoint( i*nDimension + nStartOrdinal, nDimension,
&dfStartX, &dfStartY, &dfStartZ, pSSGeomData );
GetOrdinalPoint( (i+1)*nDimension + nStartOrdinal, nDimension,
&dfMidX, &dfMidY, &dfMidZ, pSSGeomData );
GetOrdinalPoint( (i+2)*nDimension + nStartOrdinal, nDimension,
&dfEndX, &dfEndY, &dfEndZ, pSSGeomData );
OGROCIStrokeArcToOGRGeometry_Points( dfStartX, dfStartY,
dfMidX, dfMidY,
dfEndX, dfEndY,
6.0, FALSE, poLS );
}
return poLS;
}
/* -------------------------------------------------------------------- */
/* Handle polygon rings. Treat curves as if they were */
/* linestrings. */
/* -------------------------------------------------------------------- */
else if( nEType % 1000 == 3 && nInterpretation == 1 )
{
OGRLinearRing *poLS = new OGRLinearRing();
int nPointCount = nElemOrdCount / nDimension, i;
poLS->setNumPoints( nPointCount );
for( i = 0; i < nPointCount; i++ )
{
double dfX, dfY, dfZ = 0.0;
GetOrdinalPoint( i*nDimension + nStartOrdinal, nDimension,
&dfX, &dfY, &dfZ, pSSGeomData );
if (nDimension == 3)
poLS->setPoint( i, dfX, dfY, dfZ );
else
poLS->setPoint( i, dfX, dfY );
}
return poLS;
}
/* -------------------------------------------------------------------- */
/* Handle polygon rings made of circular arcs. */
/* -------------------------------------------------------------------- */
else if( nEType % 1000 == 3 && nInterpretation == 2 )
{
OGRLineString *poLS = new OGRLinearRing();
int nPointCount = nElemOrdCount / nDimension, i;
for( i = 0; i < nPointCount-2; i += 2 )
{
double dfStartX, dfStartY, dfStartZ = 0.0;
double dfMidX, dfMidY, dfMidZ = 0.0;
double dfEndX, dfEndY, dfEndZ = 0.0;
GetOrdinalPoint( i*nDimension + nStartOrdinal, nDimension,
&dfStartX, &dfStartY, &dfStartZ, pSSGeomData );
GetOrdinalPoint( (i+1)*nDimension + nStartOrdinal, nDimension,
&dfMidX, &dfMidY, &dfMidZ, pSSGeomData );
GetOrdinalPoint( (i+2)*nDimension + nStartOrdinal, nDimension,
&dfEndX, &dfEndY, &dfEndZ, pSSGeomData );
OGROCIStrokeArcToOGRGeometry_Points( dfStartX, dfStartY,
dfMidX, dfMidY,
dfEndX, dfEndY,
6.0, FALSE, poLS );
}
return poLS;
}
/* -------------------------------------------------------------------- */
/* Handle rectangle definitions ... translate into a linear ring. */
/* -------------------------------------------------------------------- */
else if( nEType % 1000 == 3 && nInterpretation == 3 )
{
OGRLinearRing *poLS = new OGRLinearRing();
double dfX1, dfY1, dfZ1 = 0.0;
double dfX2, dfY2, dfZ2 = 0.0;
GetOrdinalPoint( nStartOrdinal, nDimension,
&dfX1, &dfY1, &dfZ1, pSSGeomData );
GetOrdinalPoint( nStartOrdinal + nDimension, nDimension,
&dfX2, &dfY2, &dfZ2, pSSGeomData );
poLS->setNumPoints( 5 );
poLS->setPoint( 0, dfX1, dfY1, dfZ1 );
poLS->setPoint( 1, dfX2, dfY1, dfZ1 );
poLS->setPoint( 2, dfX2, dfY2, dfZ2 );
poLS->setPoint( 3, dfX1, dfY2, dfZ2 );
poLS->setPoint( 4, dfX1, dfY1, dfZ1 );
return poLS;
}
/* -------------------------------------------------------------------- */
/* Handle circle definitions ... translate into a linear ring. */
/* -------------------------------------------------------------------- */
else if( nEType % 100 == 3 && nInterpretation == 4 )
{
OGRLinearRing *poLS = new OGRLinearRing();
double dfX1, dfY1, dfZ1 = 0.0;
double dfX2, dfY2, dfZ2 = 0.0;
double dfX3, dfY3, dfZ3 = 0.0;
GetOrdinalPoint( nStartOrdinal, nDimension,
&dfX1, &dfY1, &dfZ1, pSSGeomData );
GetOrdinalPoint( nStartOrdinal + nDimension, nDimension,
&dfX2, &dfY2, &dfZ2, pSSGeomData );
GetOrdinalPoint( nStartOrdinal + nDimension*2, nDimension,
&dfX3, &dfY3, &dfZ3, pSSGeomData );
OGROCIStrokeArcToOGRGeometry_Points( dfX1, dfY1,
dfX2, dfY2,
dfX3, dfY3,
6.0, TRUE, poLS );
return poLS;
}
/* -------------------------------------------------------------------- */
/* Handle compound line strings and polygon rings. */
/* */
/* This is quite complicated since we need to consume several */
/* following elements, and merge the resulting geometries. */
/* -------------------------------------------------------------------- */
else if( nEType == 4 || nEType % 100 == 5 )
{
int nSubElementCount = nInterpretation;
OGRLineString *poLS, *poElemLS;
int nElemCount, nTotalOrdCount;
if( nEType == 4 )
poLS = new OGRLineString();
else
poLS = new OGRLinearRing();
nElemCount = pSSGeomData->GetElemInfo()->size();
nTotalOrdCount = pSSGeomData->GetOrdinates()->size();
for( *piElement += 3; nSubElementCount-- > 0; *piElement += 3 )
{
//loadelementinfo
nStartOrdinal = pSSGeomData->GetElemInfo()->at( *piElement );
nEType = pSSGeomData->GetElemInfo()->at( *piElement + 1);
nInterpretation = pSSGeomData->GetElemInfo()->at( *piElement + 2 );
if( *piElement < nElemCount-3 )
{
int nNextStartOrdinal = pSSGeomData->GetElemInfo()->at( *piElement + 3);
nElemOrdCount = nNextStartOrdinal - nStartOrdinal;
}
else
nElemOrdCount = nTotalOrdCount - nStartOrdinal + 1;
// Adjust for repeated end point except for last element.
if( nSubElementCount > 0 )
nElemOrdCount += nDimension;
// translate element.
poElemLS = (OGRLineString *)
TranslateGeometryElement( piElement, nGType, nDimension,
nEType, nInterpretation,
nStartOrdinal - 1, nElemOrdCount, pSSGeomData );
// Try to append to our aggregate linestring/ring
if( poElemLS )
{
if( poLS->getNumPoints() > 0 )
{
assert(
poElemLS->getX(0) == poLS->getX(poLS->getNumPoints()-1)
&& poElemLS->getY(0) ==poLS->getY(poLS->getNumPoints()-1));
poLS->addSubLineString( poElemLS, 1 );
}
else
poLS->addSubLineString( poElemLS, 0 );
//delete poElemLS;
}
}
*piElement -= 3;
return poLS;
}
/* -------------------------------------------------------------------- */
/* Otherwise it is apparently unsupported. */
/* -------------------------------------------------------------------- */
else
{
assert( false );
}
return NULL;
}
OGRGeometry* TranslateGeometry( SSDataBase::SSDBSDOGeometry* pSdoGeometry )
{
SSDataBase::SSGeomData * pSSGeomData = dynamic_cast 《SSDataBase::SSGeomData*>( pSdoGeometry->GetPrivateData() );
int nElemCount, nOrdCount;
nElemCount = pSSGeomData->GetElemInfo()->size();
nOrdCount = pSSGeomData->GetOrdinates()->size();
/* -------------------------------------------------------------------- */
/* Get the GType. */
/* -------------------------------------------------------------------- */
int nGType = *( pSSGeomData->GetGType() );
/* -------------------------------------------------------------------- */
/* Establish the dimension. */
/* -------------------------------------------------------------------- */
int nDimension = MAX(2,(nGType / 1000));
/* -------------------------------------------------------------------- */
/* Handle point data directly from built-in point info. */
/* -------------------------------------------------------------------- */
if( ORA_GTYPE_MATCH(nGType,1) && ( pSSGeomData->GetGeomPoint() != NULL ) )
{
double dfX, dfY, dfZ = 0.0;
dfX = *( pSSGeomData->GetGeomPoint()->GetX() );
dfY = *( pSSGeomData->GetGeomPoint()->GetY() );
dfZ = *( pSSGeomData->GetGeomPoint()->GetZ() );
if( nDimension == 3 )
return new OGRPoint( dfX, dfY, dfZ );
else
return new OGRPoint( dfX, dfY );
}
/* -------------------------------------------------------------------- */
/* If this is a sort of container geometry, create the */
/* container now. */
/* -------------------------------------------------------------------- */
OGRGeometryCollection *poCollection = NULL;
OGRPolygon *poPolygon = NULL;
OGRGeometry *poParent = NULL;
OGRLineString *poLS = NULL;
if( ORA_GTYPE_MATCH(nGType,2))
poLS = new OGRLineString();
else if( ORA_GTYPE_MATCH(nGType,3) )
poParent = poPolygon = new OGRPolygon();
else if( ORA_GTYPE_MATCH(nGType,4) )
poParent = poCollection = new OGRGeometryCollection();
else if( ORA_GTYPE_MATCH(nGType,5) )
poParent = poCollection = new OGRMultiPoint();
else if( ORA_GTYPE_MATCH(nGType,6) )
poParent = poCollection = new OGRMultiLineString();
else if( ORA_GTYPE_MATCH(nGType,7) )
poParent = poCollection = new OGRMultiPolygon();
/* ==================================================================== */
/* Loop over the component elements. */
/* ==================================================================== */
//每个SDO_ELEM_INFO属性单元由:SDO_STARTING_OFFSET、SDO_ETYPE 和SDO_INTERPRETATION 组成
for( int iElement = 0; iElement < nElemCount; iElement += 3 )
{
int nInterpretation, nEType;
int nStartOrdinal, nElemOrdCount;
/* -------------------------------------------------------------------- */
/* Get the details about element from the elem_info array. */
/* -------------------------------------------------------------------- */
nStartOrdinal = pSSGeomData->GetElemInfo()->at( iElement );
nEType = pSSGeomData->GetElemInfo()->at( iElement + 1);
nInterpretation = pSSGeomData->GetElemInfo()->at( iElement + 2 );
if( iElement < nElemCount-3 )
{
int nNextStartOrdinal = pSSGeomData->GetElemInfo()->at( iElement + 3);
nElemOrdCount = nNextStartOrdinal - nStartOrdinal;
}
else
nElemOrdCount = nOrdCount - nStartOrdinal + 1;
/* -------------------------------------------------------------------- */
/* Translate this element. */
/* -------------------------------------------------------------------- */
OGRGeometry *poGeom;
poGeom = TranslateGeometryElement( &iElement, nGType, nDimension,
nEType, nInterpretation,
nStartOrdinal - 1, nElemOrdCount, pSSGeomData );
if( poGeom == NULL )
return NULL;
/* -------------------------------------------------------------------- */
/* Based on GType do what is appropriate. */
/* -------------------------------------------------------------------- */
if( ORA_GTYPE_MATCH(nGType,2) )
{
//复合线已完整,
assert(wkbFlatten(poGeom->getGeometryType()) == wkbLineString);
return poGeom;
}
else if( ORA_GTYPE_MATCH(nGType,1) )
{
assert(wkbFlatten(poGeom->getGeometryType()) == wkbPoint);
return poGeom;
}
else if( ORA_GTYPE_MATCH(nGType,3) )
{
assert(wkbFlatten(poGeom->getGeometryType()) == wkbLineString );
poPolygon->addRingDirectly( (OGRLinearRing *) poGeom );
}
else
{
assert( poCollection != NULL );
if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint )
{
int i;
OGRMultiPoint *poMP = (OGRMultiPoint *) poGeom;
for( i = 0; i < poMP->getNumGeometries(); i++ )
poCollection->addGeometry( poMP->getGeometryRef(i) );
delete poMP;
}
else if( nEType % 1000 == 3 )
{
/* its one poly ring, create new poly or add to existing */
if( nEType == 1003 )
{
if( poPolygon != NULL
&& poPolygon->getExteriorRing() != NULL )
{
poCollection->addGeometryDirectly( poPolygon );
poPolygon = NULL;
}
poPolygon = new OGRPolygon();
}
if( poPolygon != NULL )
poPolygon->addRingDirectly( (OGRLinearRing *) poGeom );
else
{
assert( poPolygon != NULL );
}
}
else
poCollection->addGeometryDirectly( poGeom );
}
}
if( poCollection != NULL
&& poPolygon != NULL )
poCollection->addGeometryDirectly( poPolygon );
/* -------------------------------------------------------------------- */
/* Return resulting collection geometry. */
/* -------------------------------------------------------------------- */
if( poCollection == NULL )
return poPolygon;
else
return poCollection;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void PushElemInfo( int nOffset, int nEType, int nInterp, SSDataBase::SSGeomData* &pSSGeomData, int& nElemInfoCount )
{
std::vector* pElementInfo = pSSGeomData->GetElemInfo();
int nElemInfoMax = pElementInfo->size();
if( nElemInfoCount+3 >= nElemInfoMax )
{
nElemInfoMax = nElemInfoMax * 2 + 100;
pElementInfo->reserve( nElemInfoMax );
}
pElementInfo->push_back( nOffset );
nElemInfoCount++;
pElementInfo->push_back( nEType );
nEType++;
pElementInfo->push_back( nInterp );
nInterp++;
// pElementInfo->at( nElemInfoCount++ ) = nOffset;
// pElementInfo->at( nElemInfoCount++ ) = nEType;
// pElementInfo->at( nElemInfoCount++ ) = nInterp;
}
void PushOrdinal( double dfOrd, SSDataBase::SSGeomData* &pSSGeomData, int& nOrdinalCount )
{
std::vector * pOrdinates = pSSGeomData->GetOrdinates();
int nOrdinalMax = pOrdinates->size();
if( nOrdinalCount == nOrdinalMax )
{
nOrdinalMax = nOrdinalMax * 2 + 100;
pOrdinates->reserve( nOrdinalMax );
}
pOrdinates->push_back( dfOrd );
nOrdinalCount++;
/* pOrdinates->at( nOrdinalCount++ ) = dfOrd;*/
}
void TranslateElementGroup( OGRGeometry poGeometry, int nDimension, SSDataBase::SSGeomData &pSSGeomData, int& nOrdinalCount, int& nElemInfoCount )
{
switch( wkbFlatten(poGeometry->getGeometryType()) )
{
case wkbPoint:
{
OGRPoint poPoint = (OGRPoint ) poGeometry;
PushElemInfo( nOrdinalCount+1, 1, 1, pSSGeomData, nElemInfoCount );
PushOrdinal( poPoint->getX(), pSSGeomData, nOrdinalCount );
PushOrdinal( poPoint->getY(), pSSGeomData, nOrdinalCount );
if( nDimension == 3 )
PushOrdinal( poPoint->getZ(), pSSGeomData, nOrdinalCount );
}
break;
case wkbLineString:
{
OGRLineString *poLine = (OGRLineString *) poGeometry;
int iVert;
PushElemInfo( nOrdinalCount+1, 2, 1, pSSGeomData, nElemInfoCount );
for( iVert = 0; iVert < poLine->getNumPoints(); iVert++ )
{
PushOrdinal( poLine->getX(iVert), pSSGeomData, nOrdinalCount );
PushOrdinal( poLine->getY(iVert), pSSGeomData, nOrdinalCount );
if( nDimension == 3 )
PushOrdinal( poLine->getZ(iVert), pSSGeomData, nOrdinalCount );
}
}
break;
case wkbPolygon:
{
OGRPolygon *poPoly = (OGRPolygon *) poGeometry;
int iRing;
for( iRing = -1; iRing < poPoly->getNumInteriorRings(); iRing++ )
{
OGRLinearRing *poRing;
int iVert;
if( iRing == -1 )
poRing = poPoly->getExteriorRing();
else
poRing = poPoly->getInteriorRing(iRing);
if( iRing == -1 )
PushElemInfo( nOrdinalCount+1, 1003, 1, pSSGeomData, nElemInfoCount );
else
PushElemInfo( nOrdinalCount+1, 2003, 1, pSSGeomData, nElemInfoCount );
if( (iRing == -1 && poRing->isClockwise())
|| (iRing != -1 && !poRing->isClockwise()) )
{
for( iVert = poRing->getNumPoints()-1; iVert >= 0; iVert-- )
{
PushOrdinal( poRing->getX(iVert), pSSGeomData, nOrdinalCount );
PushOrdinal( poRing->getY(iVert), pSSGeomData, nOrdinalCount );
if( nDimension == 3 )
PushOrdinal( poRing->getZ(iVert), pSSGeomData, nOrdinalCount );
}
}
else
{
for( iVert = 0; iVert < poRing->getNumPoints(); iVert++ )
{
PushOrdinal( poRing->getX(iVert), pSSGeomData, nOrdinalCount );
PushOrdinal( poRing->getY(iVert), pSSGeomData, nOrdinalCount );
if( nDimension == 3 )
PushOrdinal( poRing->getZ(iVert), pSSGeomData, nOrdinalCount );
}
}
}
}
break;
default:
{
assert(false);
}
}
}
//////////////////////////////////OGRGeometry ->SDOGeometry//////////////////
SSDataBase::SSDBSDOGeometry* TranslateToSDOGeometry( OGRGeometry * poGeometry, int *pnGType )
{
int nDimension = 3;
int nOrdinalCount = 0;
int nElemInfoCount = 0;
if( poGeometry == NULL )
return NULL;
SSDataBase::SSDBSDOGeometry* pSSDBObject = dynamic_cast< SSDataBase::SSDBSDOGeometry* >( SSDataBase::SSDBObject::CreateObject(std::string("MDSYS.SDO_GEOMETRY")));
assert(pSSDBObject);
SSDataBase::SSGeomData* pSSGeomData = dynamic_cast<SSDataBase::SSGeomData*>( pSSDBObject->CreatePrivateData() );
assert( pSSGeomData );
/* ==================================================================== */
/* Handle a point geometry. */
/* ==================================================================== */
if( wkbFlatten(poGeometry->getGeometryType()) == wkbPoint )
{
*pnGType = nDimension * 1000 + 1;
OGRPoint *poPoint = (OGRPoint *) poGeometry;
double dfX, dfY, dfZ;
dfX = poPoint->getX();
dfY = poPoint->getY();
dfZ = poPoint->getZ();
if( nDimension == 2 )
pSSGeomData->SetGeomPoint( &dfX, &dfY, NULL );
else
pSSGeomData->SetGeomPoint( &dfX, &dfY, &dfZ );
}
/* ==================================================================== */
/* Handle a line string geometry. */
/* ==================================================================== */
else if( wkbFlatten(poGeometry->getGeometryType()) == wkbLineString )
{
*pnGType = nDimension * 1000 + 2;
TranslateElementGroup( poGeometry, nDimension, pSSGeomData, nOrdinalCount, nElemInfoCount );
}
/* ==================================================================== */
/* Handle a polygon geometry. */
/* ==================================================================== */
else if( wkbFlatten(poGeometry->getGeometryType()) == wkbPolygon )
{
*pnGType = nDimension == 2 ? 2003 : 3003;
TranslateElementGroup( poGeometry, nDimension, pSSGeomData, nOrdinalCount, nElemInfoCount );
}
/* ==================================================================== */
/* Handle a multi point geometry. */
/* ==================================================================== */
else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint )
{
OGRMultiPoint *poMP = (OGRMultiPoint *) poGeometry;
int iVert;
*pnGType = nDimension*1000 + 5;
PushElemInfo( 1, 1, poMP->getNumGeometries(), pSSGeomData, nElemInfoCount );
for( iVert = 0; iVert < poMP->getNumGeometries(); iVert++ )
{
OGRPoint *poPoint = (OGRPoint *)poMP->getGeometryRef( iVert );
PushOrdinal( poPoint->getX(), pSSGeomData, nOrdinalCount );
PushOrdinal( poPoint->getY(), pSSGeomData, nOrdinalCount );
if( nDimension == 3 )
PushOrdinal( poPoint->getZ(), pSSGeomData, nOrdinalCount );
}
}
/* ==================================================================== */
/* Handle other geometry collections. */
/* ==================================================================== */
else
{
/* -------------------------------------------------------------------- */
/* Identify the GType. */
/* -------------------------------------------------------------------- */
if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString )
*pnGType = nDimension * 1000 + 6;
else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon )
*pnGType = nDimension * 1000 + 7;
else if( wkbFlatten(poGeometry->getGeometryType())
== wkbGeometryCollection )
*pnGType = nDimension * 1000 + 4;
else
{
assert( false );
}
/* -------------------------------------------------------------------- */
/* Translate each child in turn. */
/* -------------------------------------------------------------------- */
OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeometry;
int iChild;
for( iChild = 0; iChild < poGC->getNumGeometries(); iChild++ )
TranslateElementGroup( poGC->getGeometryRef(iChild), nDimension, pSSGeomData, nOrdinalCount, nElemInfoCount );
}
pSSGeomData->SetGType( *pnGType );
return pSSDBObject;
}
文章参考:爱图–UpdooGIS博客内容,oraclespatial 空间信息管理书籍。
代码参考:ogr源码
转载自:https://blog.csdn.net/lly276586465/article/details/78686383