EVOLUTION-MANAGER
Edit File: ogrcadlayer.cpp
/******************************************************************************* * Project: OGR CAD Driver * Purpose: Implements driver based on libopencad * Author: Alexandr Borzykh, mush3d at gmail.com * Author: Dmitry Baryshnikov, polimax@mail.ru * Language: C++ ******************************************************************************* * The MIT License (MIT) * * Copyright (c) 2016 Alexandr Borzykh * Copyright (c) 2016, NextGIS <info@nextgis.com> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. *******************************************************************************/ #include "cpl_conv.h" #include "ogr_cad.h" #include <iomanip> #include <sstream> #define FIELD_NAME_GEOMTYPE "cadgeom_type" #define FIELD_NAME_THICKNESS "thickness" #define FIELD_NAME_COLOR "color" #define FIELD_NAME_EXT_DATA "extentity_data" #define FIELD_NAME_TEXT "text" static const double DEG2RAD = M_PI / 180.0; // UNUSED static const double RAD2DEG = 1.0 / DEG2RAD; OGRCADLayer::OGRCADLayer( CADLayer &poCADLayer_, OGRSpatialReference *poSR, int nEncoding) : poSpatialRef( poSR ), poCADLayer( poCADLayer_ ), nDWGEncoding( nEncoding) { nNextFID = 0; if( poSpatialRef ) poSpatialRef->Reference(); poFeatureDefn = new OGRFeatureDefn( CADRecode( poCADLayer_.getName(), nDWGEncoding ) ); // Setting up layer geometry type OGRwkbGeometryType eGeomType; char dLineStringPresented = 0; char dCircularStringPresented = 0; char dPointPresented = 0; char dPolygonPresented = 0; std::vector<CADObject::ObjectType> aePresentedGeometryTypes = poCADLayer.getGeometryTypes(); for( size_t i = 0; i < aePresentedGeometryTypes.size(); ++i ) { switch( aePresentedGeometryTypes[i] ) { case CADObject::ATTDEF: case CADObject::TEXT: case CADObject::MTEXT: case CADObject::POINT: dPointPresented = 1; break; case CADObject::CIRCLE: dCircularStringPresented = 1; break; case CADObject::SPLINE: case CADObject::ELLIPSE: case CADObject::ARC: case CADObject::POLYLINE3D: case CADObject::POLYLINE2D: case CADObject::LWPOLYLINE: case CADObject::LINE: dLineStringPresented = 1; break; case CADObject::FACE3D: case CADObject::SOLID: dPolygonPresented = 1; break; default: break; } } if( ( dLineStringPresented + dCircularStringPresented + dPointPresented + dPolygonPresented ) > 1 ) { eGeomType = wkbGeometryCollection; } else { if( dLineStringPresented ) { eGeomType = wkbLineString; } else if( dCircularStringPresented ) { eGeomType = wkbCircularString; } else if( dPointPresented ) { eGeomType = wkbPoint; } else if( dPolygonPresented ) { eGeomType = wkbPolygon; } else { eGeomType = wkbUnknown; } } poFeatureDefn->SetGeomType( eGeomType ); OGRFieldDefn oClassField( FIELD_NAME_GEOMTYPE, OFTString ); poFeatureDefn->AddFieldDefn( &oClassField ); OGRFieldDefn oLinetypeField( FIELD_NAME_THICKNESS, OFTReal ); poFeatureDefn->AddFieldDefn( &oLinetypeField ); OGRFieldDefn oColorField( FIELD_NAME_COLOR, OFTString ); poFeatureDefn->AddFieldDefn( &oColorField ); OGRFieldDefn oExtendedField( FIELD_NAME_EXT_DATA, OFTString ); poFeatureDefn->AddFieldDefn( &oExtendedField ); OGRFieldDefn oTextField( FIELD_NAME_TEXT, OFTString ); poFeatureDefn->AddFieldDefn( &oTextField ); auto oAttrTags = poCADLayer.getAttributesTags(); for( const std::string & osTag : oAttrTags ) { auto ret = asFeaturesAttributes.insert( osTag ); if( ret.second == true) { OGRFieldDefn oAttrField( osTag.c_str(), OFTString ); poFeatureDefn->AddFieldDefn( &oAttrField ); } } // Applying spatial ref info if (poFeatureDefn->GetGeomFieldCount() != 0) poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef( poSpatialRef ); SetDescription( poFeatureDefn->GetName() ); poFeatureDefn->Reference(); } GIntBig OGRCADLayer::GetFeatureCount( int bForce ) { if( m_poFilterGeom != NULL || m_poAttrQuery != NULL ) return OGRLayer::GetFeatureCount( bForce ); return poCADLayer.getGeometryCount(); } OGRCADLayer::~OGRCADLayer() { if( poSpatialRef ) poSpatialRef->Release(); poFeatureDefn->Release(); } void OGRCADLayer::ResetReading() { nNextFID = 0; } OGRFeature *OGRCADLayer::GetNextFeature() { OGRFeature *poFeature = GetFeature( nNextFID ); ++nNextFID; if( poFeature == NULL ) return NULL; if( ( m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeometryRef() ) ) && ( m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature ) ) ) { return poFeature; } return NULL; } OGRFeature *OGRCADLayer::GetFeature( GIntBig nFID ) { if( poCADLayer.getGeometryCount() <= static_cast<size_t>(nFID) || nFID < 0 ) { return NULL; } OGRFeature *poFeature = NULL; CADGeometry *poCADGeometry = poCADLayer.getGeometry( nFID ); if( NULL == poCADGeometry || GetLastErrorCode() != CADErrorCodes::SUCCESS ) { CPLError( CE_Failure, CPLE_NotSupported, "Failed to get geometry with ID = " CPL_FRMT_GIB " from layer \"%s\". Libopencad errorcode: %d", nFID, poCADLayer.getName().c_str(), GetLastErrorCode() ); return NULL; } poFeature = new OGRFeature( poFeatureDefn ); poFeature->SetFID( nFID ); poFeature->SetField( FIELD_NAME_THICKNESS, poCADGeometry->getThickness() ); if( !poCADGeometry->getEED().empty() ) { std::vector<std::string> asGeometryEED = poCADGeometry->getEED(); std::string sEEDAsOneString = ""; for ( std::vector<std::string>::const_iterator iter = asGeometryEED.cbegin(); iter != asGeometryEED.cend(); ++iter ) { sEEDAsOneString += *iter; sEEDAsOneString += ' '; } poFeature->SetField( FIELD_NAME_EXT_DATA, sEEDAsOneString.c_str() ); } RGBColor stRGB = poCADGeometry->getColor(); CPLString sHexColor; sHexColor.Printf("#%02X%02X%02X%02X", stRGB.R, stRGB.G, stRGB.B, 255); poFeature->SetField( FIELD_NAME_COLOR, sHexColor ); CPLString sStyle; sStyle.Printf("PEN(c:%s,w:5px)", sHexColor.c_str()); poFeature->SetStyleString( sStyle ); std::vector< CADAttrib > oBlockAttrs = poCADGeometry->getBlockAttributes(); for( const CADAttrib& oAttrib : oBlockAttrs ) { CPLString osTag = oAttrib.getTag(); auto featureAttrIt = asFeaturesAttributes.find( osTag ); if( featureAttrIt != asFeaturesAttributes.end()) { poFeature->SetField(*featureAttrIt, oAttrib.getTextValue().c_str()); } } switch( poCADGeometry->getType() ) { case CADGeometry::POINT: { CADPoint3D * const poCADPoint = ( CADPoint3D* ) poCADGeometry; CADVector stPositionVector = poCADPoint->getPosition(); poFeature->SetGeometryDirectly( new OGRPoint( stPositionVector.getX(), stPositionVector.getY(), stPositionVector.getZ() ) ); poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADPoint" ); break; } case CADGeometry::LINE: { CADLine * const poCADLine = ( CADLine* ) poCADGeometry; OGRLineString *poLS = new OGRLineString(); poLS->addPoint( poCADLine->getStart().getPosition().getX(), poCADLine->getStart().getPosition().getY(), poCADLine->getStart().getPosition().getZ() ); poLS->addPoint( poCADLine->getEnd().getPosition().getX(), poCADLine->getEnd().getPosition().getY(), poCADLine->getEnd().getPosition().getZ() ); poFeature->SetGeometryDirectly( poLS ); poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADLine" ); break; } case CADGeometry::SOLID: { CADSolid * const poCADSolid = ( CADSolid* ) poCADGeometry; OGRPolygon * poPoly = new OGRPolygon(); OGRLinearRing * poLR = new OGRLinearRing(); std::vector<CADVector> astSolidCorners = poCADSolid->getCorners(); for( size_t i = 0; i < astSolidCorners.size(); ++i ) { poLR->addPoint( astSolidCorners[i].getX(), astSolidCorners[i].getY(), astSolidCorners[i].getZ()); } poPoly->addRingDirectly( poLR ); poPoly->closeRings(); poFeature->SetGeometryDirectly( poPoly ); poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADSolid" ); break; } case CADGeometry::CIRCLE: { CADCircle * poCADCircle = static_cast<CADCircle*>(poCADGeometry); OGRCircularString * poCircle = new OGRCircularString(); CADVector stCircleCenter = poCADCircle->getPosition(); OGRPoint oCirclePoint1; oCirclePoint1.setX( stCircleCenter.getX() + poCADCircle->getRadius() ); oCirclePoint1.setY( stCircleCenter.getY() + poCADCircle->getRadius() ); oCirclePoint1.setZ( stCircleCenter.getZ() ); poCircle->addPoint( &oCirclePoint1 ); OGRPoint oCirclePoint2; oCirclePoint2.setX( stCircleCenter.getX() - poCADCircle->getRadius() ); oCirclePoint2.setY( stCircleCenter.getY() - poCADCircle->getRadius() ); oCirclePoint2.setZ( stCircleCenter.getZ() ); poCircle->addPoint( &oCirclePoint2 ); // Close the circle poCircle->addPoint( &oCirclePoint1 ); /*NOTE: The alternative way: OGRGeometry *poCircle = OGRGeometryFactory::approximateArcAngles( poCADCircle->getPosition().getX(), poCADCircle->getPosition().getY(), poCADCircle->getPosition().getZ(), poCADCircle->getRadius(), poCADCircle->getRadius(), 0.0, 0.0, 360.0, 0.0 ); */ poFeature->SetGeometryDirectly( poCircle ); poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADCircle" ); break; } case CADGeometry::ARC: { CADArc * poCADArc = static_cast<CADArc*>(poCADGeometry); OGRCircularString * poCircle = new OGRCircularString(); // Need at least 3 points in arc double dfStartAngle = poCADArc->getStartingAngle() * DEG2RAD; double dfEndAngle = poCADArc->getEndingAngle() * DEG2RAD; double dfMidAngle = (dfEndAngle + dfStartAngle) / 2; CADVector stCircleCenter = poCADArc->getPosition(); OGRPoint oCirclePoint; oCirclePoint.setX( stCircleCenter.getX() + poCADArc->getRadius() * cos( dfStartAngle ) ); oCirclePoint.setY( stCircleCenter.getY() + poCADArc->getRadius() * sin( dfStartAngle ) ); oCirclePoint.setZ( stCircleCenter.getZ() ); poCircle->addPoint( &oCirclePoint ); oCirclePoint.setX( stCircleCenter.getX() + poCADArc->getRadius() * cos( dfMidAngle ) ); oCirclePoint.setY( stCircleCenter.getY() + poCADArc->getRadius() * sin( dfMidAngle ) ); oCirclePoint.setZ( stCircleCenter.getZ() ); poCircle->addPoint( &oCirclePoint ); oCirclePoint.setX( stCircleCenter.getX() + poCADArc->getRadius() * cos( dfEndAngle ) ); oCirclePoint.setY( stCircleCenter.getY() + poCADArc->getRadius() * sin( dfEndAngle ) ); oCirclePoint.setZ( stCircleCenter.getZ() ); poCircle->addPoint( &oCirclePoint ); /*NOTE: alternative way: OGRGeometry * poArc = OGRGeometryFactory::approximateArcAngles( poCADArc->getPosition().getX(), poCADArc->getPosition().getY(), poCADArc->getPosition().getZ(), poCADArc->getRadius(), poCADArc->getRadius(), 0.0, dfStartAngle, dfStartAngle > dfEndAngle ? ( dfEndAngle + 360.0f ) : dfEndAngle, 0.0 ); */ poFeature->SetGeometryDirectly( poCircle ); poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADArc" ); break; } case CADGeometry::FACE3D: { CADFace3D * const poCADFace = ( CADFace3D* ) poCADGeometry; OGRPolygon * poPoly = new OGRPolygon(); OGRLinearRing * poLR = new OGRLinearRing(); for ( size_t i = 0; i < 3; ++i ) { poLR->addPoint( poCADFace->getCorner( i ).getX(), poCADFace->getCorner( i ).getY(), poCADFace->getCorner( i ).getZ() ); } if ( !(poCADFace->getCorner( 2 ) == poCADFace->getCorner( 3 )) ) { poLR->addPoint( poCADFace->getCorner( 3 ).getX(), poCADFace->getCorner( 3 ).getY(), poCADFace->getCorner( 3 ).getZ() ); } poPoly->addRingDirectly( poLR ); poPoly->closeRings(); poFeature->SetGeometryDirectly( poPoly ); poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADFace3D" ); break; } case CADGeometry::LWPOLYLINE: { CADLWPolyline * const poCADLWPolyline = ( CADLWPolyline* ) poCADGeometry; poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADLWPolyline" ); /* * Excessive check, like in DXF driver. * I tried to make a single-point polyline, but couldnt make it. * Probably this check should be removed. */ if( poCADLWPolyline->getVertexCount() == 1 ) { poFeature->SetGeometryDirectly( new OGRPoint( poCADLWPolyline->getVertex(0).getX(), poCADLWPolyline->getVertex(0).getY(), poCADLWPolyline->getVertex(0).getZ() ) ); break; } /* * If polyline has no arcs, handle it in easy way. */ OGRLineString * poLS = new OGRLineString(); if( poCADLWPolyline->getBulges().empty() ) { for( size_t i = 0; i < poCADLWPolyline->getVertexCount(); ++i ) { CADVector stVertex = poCADLWPolyline->getVertex( i ); poLS->addPoint( stVertex.getX(), stVertex.getY(), stVertex.getZ() ); } poFeature->SetGeometryDirectly( poLS ); break; } /* * Last case - if polyline has mixed arcs and lines. */ bool bLineStringStarted = false; size_t iCurrentVertex = 0, iLastVertex = poCADLWPolyline->getVertexCount() - 1; std::vector< double > adfBulges = poCADLWPolyline->getBulges(); while( iCurrentVertex != iLastVertex ) { CADVector stCurrentVertex = poCADLWPolyline->getVertex( iCurrentVertex ); CADVector stNextVertex = poCADLWPolyline->getVertex( iCurrentVertex + 1 ); double dfLength = sqrt( pow( stNextVertex.getX() - stCurrentVertex.getX(), 2 ) + pow( stNextVertex.getY() - stCurrentVertex.getY(), 2 ) ); /* * Handling straight polyline segment. */ if( ( dfLength == 0 ) || ( adfBulges[iCurrentVertex] == 0 ) ) { if( !bLineStringStarted ) { poLS->addPoint( stCurrentVertex.getX(), stCurrentVertex.getY(), stCurrentVertex.getZ() ); bLineStringStarted = true; } poLS->addPoint( stNextVertex.getX(), stNextVertex.getY(), stNextVertex.getZ() ); } else { double dfSegmentBulge = adfBulges[iCurrentVertex]; double dfH = ( dfSegmentBulge * dfLength ) / 2; double dfRadius = ( dfH / 2 ) + ( dfLength * dfLength / ( 8 * dfH ) ); double dfOgrArcRotation = 0, dfOgrArcRadius = fabs( dfRadius ); /* * Set arc's direction and keep bulge positive. */ bool bClockwise = ( dfSegmentBulge < 0 ); if( bClockwise ) dfSegmentBulge *= -1; /* * Get arc's center point. */ double dfSaggita = fabs( dfSegmentBulge * ( dfLength / 2.0 ) ); double dfApo = bClockwise ? -( dfOgrArcRadius - dfSaggita ) : -( dfSaggita - dfOgrArcRadius ); CADVector stVertex; stVertex.setX( stCurrentVertex.getX() - stNextVertex.getX() ); stVertex.setY( stCurrentVertex.getY() - stNextVertex.getY() ); stVertex.setZ( stCurrentVertex.getZ() ); CADVector stMidPoint; stMidPoint.setX( stNextVertex.getX() + 0.5 * stVertex.getX() ); stMidPoint.setY( stNextVertex.getY() + 0.5 * stVertex.getY() ); stMidPoint.setZ( stVertex.getZ() ); CADVector stPperp; stPperp.setX( stVertex.getY() ); stPperp.setY( -stVertex.getX() ); double dfStPperpLength = sqrt( stPperp.getX() * stPperp.getX() + stPperp.getY() * stPperp.getY() ); // TODO: Check that length isnot 0 stPperp.setX( stPperp.getX() / dfStPperpLength ); stPperp.setY( stPperp.getY() / dfStPperpLength ); CADVector stOgrArcCenter; stOgrArcCenter.setX( stMidPoint.getX() + ( stPperp.getX() * dfApo ) ); stOgrArcCenter.setY( stMidPoint.getY() + ( stPperp.getY() * dfApo ) ); /* * Get the line's general vertical direction ( -1 = down, +1 = up ). */ double dfLineDir = stNextVertex.getY() > stCurrentVertex.getY() ? 1.0f : -1.0f; /* * Get arc's starting angle. */ double dfA = atan2( ( stOgrArcCenter.getY() - stCurrentVertex.getY() ), ( stOgrArcCenter.getX() - stCurrentVertex.getX() ) ) * DEG2RAD; if( bClockwise && ( dfLineDir == 1.0 ) ) dfA += ( dfLineDir * 180.0 ); double dfOgrArcStartAngle = dfA > 0.0 ? -( dfA - 180.0 ) : -( dfA + 180.0 ); /* * Get arc's ending angle. */ dfA = atan2( ( stOgrArcCenter.getY() - stNextVertex.getY() ), ( stOgrArcCenter.getX() - stNextVertex.getX() ) ) * DEG2RAD; if( bClockwise && ( dfLineDir == 1.0 ) ) dfA += ( dfLineDir * 180.0 ); double dfOgrArcEndAngle = dfA > 0.0 ? -( dfA - 180.0 ) : -( dfA + 180.0 ); if( !bClockwise && ( dfOgrArcStartAngle < dfOgrArcEndAngle) ) dfOgrArcEndAngle = -180.0 + ( dfLineDir * dfA ); if( bClockwise && ( dfOgrArcStartAngle > dfOgrArcEndAngle ) ) dfOgrArcEndAngle += 360.0; /* * Flip arc's rotation if necessary. */ if( bClockwise && ( dfLineDir == 1.0 ) ) dfOgrArcRotation = dfLineDir * 180.0; /* * Tesselate the arc segment and append to the linestring. */ OGRLineString * poArcpoLS = ( OGRLineString * ) OGRGeometryFactory::approximateArcAngles( stOgrArcCenter.getX(), stOgrArcCenter.getY(), stOgrArcCenter.getZ(), dfOgrArcRadius, dfOgrArcRadius, dfOgrArcRotation, dfOgrArcStartAngle,dfOgrArcEndAngle, 0.0 ); poLS->addSubLineString( poArcpoLS ); delete( poArcpoLS ); } ++iCurrentVertex; } if( poCADLWPolyline->isClosed() ) { poLS->addPoint( poCADLWPolyline->getVertex(0).getX(), poCADLWPolyline->getVertex(0).getY(), poCADLWPolyline->getVertex(0).getZ() ); } poFeature->SetGeometryDirectly( poLS ); poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADLWPolyline" ); break; } // TODO: Unsupported smooth lines case CADGeometry::POLYLINE3D: { CADPolyline3D * const poCADPolyline3D = ( CADPolyline3D* ) poCADGeometry; OGRLineString * poLS = new OGRLineString(); for( size_t i = 0; i < poCADPolyline3D->getVertexCount(); ++i ) { CADVector stVertex = poCADPolyline3D->getVertex( i ); poLS->addPoint( stVertex.getX(), stVertex.getY(), stVertex.getZ() ); } poFeature->SetGeometryDirectly( poLS ); poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADPolyline3D" ); break; } case CADGeometry::TEXT: { CADText * const poCADText = ( CADText * ) poCADGeometry; OGRPoint * poPoint = new OGRPoint( poCADText->getPosition().getX(), poCADText->getPosition().getY(), poCADText->getPosition().getZ() ); CPLString sTextValue = CADRecode( poCADText->getTextValue(), nDWGEncoding ); poFeature->SetField( FIELD_NAME_TEXT, sTextValue ); poFeature->SetGeometryDirectly( poPoint ); poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADText" ); sStyle.Printf("LABEL(f:\"Arial\",t:\"%s\",c:%s)", sTextValue.c_str(), sHexColor.c_str()); poFeature->SetStyleString( sStyle ); break; } case CADGeometry::MTEXT: { CADMText * const poCADMText = ( CADMText * ) poCADGeometry; OGRPoint * poPoint = new OGRPoint( poCADMText->getPosition().getX(), poCADMText->getPosition().getY(), poCADMText->getPosition().getZ() ); CPLString sTextValue = CADRecode( poCADMText->getTextValue(), nDWGEncoding ); poFeature->SetField( FIELD_NAME_TEXT, sTextValue ); poFeature->SetGeometryDirectly( poPoint ); poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADMText" ); sStyle.Printf("LABEL(f:\"Arial\",t:\"%s\",c:%s)", sTextValue.c_str(), sHexColor.c_str()); poFeature->SetStyleString( sStyle ); break; } case CADGeometry::SPLINE: { CADSpline * const poCADSpline = ( CADSpline * ) poCADGeometry; OGRLineString * poLS = new OGRLineString(); // TODO: Interpolate spline as points or curves for( size_t i = 0; i < poCADSpline->getControlPoints().size(); ++i ) { poLS->addPoint( poCADSpline->getControlPoints()[i].getX(), poCADSpline->getControlPoints()[i].getY(), poCADSpline->getControlPoints()[i].getZ() ); } poFeature->SetGeometryDirectly( poLS ); poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADSpline" ); break; } case CADGeometry::ELLIPSE: { CADEllipse * poCADEllipse = static_cast<CADEllipse*>(poCADGeometry); // FIXME: Start/end angles should be swapped to work exactly as DXF driver. // is it correct? double dfStartAngle = -1 * poCADEllipse->getEndingAngle() * DEG2RAD; double dfEndAngle = -1 * poCADEllipse->getStartingAngle() * DEG2RAD; double dfAxisRatio = poCADEllipse->getAxisRatio(); if( dfStartAngle > dfEndAngle ) dfEndAngle += 360.0; CADVector vectPosition = poCADEllipse->getPosition(); CADVector vectSMAxis = poCADEllipse->getSMAxis(); double dfPrimaryRadius, dfSecondaryRadius; double dfRotation; dfPrimaryRadius = sqrt( vectSMAxis.getX() * vectSMAxis.getX() + vectSMAxis.getY() * vectSMAxis.getY() + vectSMAxis.getZ() * vectSMAxis.getZ() ); dfSecondaryRadius = dfAxisRatio * dfPrimaryRadius; dfRotation = -1 * atan2( vectSMAxis.getY(), vectSMAxis.getX() ) * DEG2RAD; OGRGeometry *poEllipse = OGRGeometryFactory::approximateArcAngles( vectPosition.getX(), vectPosition.getY(), vectPosition.getZ(), dfPrimaryRadius, dfSecondaryRadius, dfRotation, dfStartAngle, dfEndAngle, 0.0 ); poFeature->SetGeometryDirectly( poEllipse ); poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADEllipse" ); break; } case CADGeometry::ATTDEF: { CADAttdef * const poCADAttdef = ( CADAttdef* ) poCADGeometry; OGRPoint * poPoint = new OGRPoint( poCADAttdef->getPosition().getX(), poCADAttdef->getPosition().getY(), poCADAttdef->getPosition().getZ() ); CPLString sTextValue = CADRecode( poCADAttdef->getTag(), nDWGEncoding ); poFeature->SetField( FIELD_NAME_TEXT, sTextValue ); poFeature->SetGeometryDirectly( poPoint ); poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADAttdef" ); sStyle.Printf("LABEL(f:\"Arial\",t:\"%s\",c:%s)", sTextValue.c_str(), sHexColor.c_str()); poFeature->SetStyleString( sStyle ); break; } default: { CPLError( CE_Warning, CPLE_NotSupported, "Unhandled feature. Skipping it." ); poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADUnknown" ); delete poCADGeometry; return poFeature; } } delete poCADGeometry; poFeature->GetGeometryRef()->assignSpatialReference( poSpatialRef ); return poFeature; }