OGRCircularString* make() { OGRCircularString* poCircularString = new OGRCircularString(); poCircularString->addPoint(1.0, 2.0, 3.0); poCircularString->addPoint(1.1, 2.1, 3.1); poCircularString->addPoint(1.2, 2.2, 3.2); return poCircularString; }
// [[Rcpp::export]] Rcpp::List CPL_circularstring_to_linestring(Rcpp::List sfc) { // need to pass more parameters? std::vector<OGRGeometry *> g = ogr_from_sfc(sfc, NULL); std::vector<OGRGeometry *> out(g.size()); for (size_t i = 0; i < g.size(); i++) { OGRCircularString *cs = (OGRCircularString *) g[i]; out[i] = cs->CurveToLine(); OGRGeometryFactory::destroyGeometry(g[i]); } return sfc_from_ogr(out, true); // destroys out; }
OGRCompoundCurve* make() { OGRCompoundCurve* poCompoundCurve = new OGRCompoundCurve(); poCompoundCurve->addCurveDirectly(make<OGRLineString>()); OGRCircularString* poCircularString = make<OGRCircularString>(); poCircularString->reversePoints(); poCompoundCurve->addCurveDirectly(poCircularString); return poCompoundCurve; }
OGRCircularString *ILI2Reader::getArc(DOMElement *elem) { // elem -> ARC OGRCircularString *arc = new OGRCircularString(); // previous point -> start point OGRPoint *ptStart = getPoint((DOMElement *)elem->getPreviousSibling()); // COORD or ARC // end point OGRPoint *ptEnd = new OGRPoint(); // point on the arc OGRPoint *ptOnArc = new OGRPoint(); // double radius = 0; // radius DOMElement *arcElem = (DOMElement *)elem->getFirstChild(); while (arcElem != NULL) { char* pszTagName = XMLString::transcode(arcElem->getTagName()); char* pszObjValue = getObjValue(arcElem); if (cmpStr("C1", pszTagName) == 0) ptEnd->setX(CPLAtof(pszObjValue)); else if (cmpStr("C2", pszTagName) == 0) ptEnd->setY(CPLAtof(pszObjValue)); else if (cmpStr("C3", pszTagName) == 0) ptEnd->setZ(CPLAtof(pszObjValue)); else if (cmpStr("A1", pszTagName) == 0) ptOnArc->setX(CPLAtof(pszObjValue)); else if (cmpStr("A2", pszTagName) == 0) ptOnArc->setY(CPLAtof(pszObjValue)); else if (cmpStr("A3", pszTagName) == 0) ptOnArc->setZ(CPLAtof(pszObjValue)); else if (cmpStr("R", pszTagName) == 0) { // radius = CPLAtof(pszObjValue); } CPLFree(pszObjValue); XMLString::release(&pszTagName); arcElem = (DOMElement *)arcElem->getNextSibling(); } arc->addPoint(ptStart); arc->addPoint(ptOnArc); arc->addPoint(ptEnd); delete ptStart; delete ptOnArc; delete ptEnd; return arc; }
void ILI1Reader::ReadGeom( char **stgeom, int geomIdx, OGRwkbGeometryType eType, OGRFeature *feature ) { #ifdef DEBUG_VERBOSE CPLDebug( "OGR_ILI", "ILI1Reader::ReadGeom geomIdx: %d OGRGeometryType: %s", geomIdx, OGRGeometryTypeToName(eType) ); #endif if (eType == wkbNone) { CPLError( CE_Warning, CPLE_AppDefined, "Calling ILI1Reader::ReadGeom with wkbNone" ); } // Initialize geometry. OGRCompoundCurve *ogrCurve = new OGRCompoundCurve(); OGRCurvePolygon *ogrPoly = NULL; //current polygon OGRMultiCurve *ogrMultiLine = NULL; //current multi line if (eType == wkbMultiCurve || eType == wkbMultiLineString) { ogrMultiLine = new OGRMultiCurve(); } else if (eType == wkbPolygon || eType == wkbCurvePolygon) { ogrPoly = new OGRCurvePolygon(); } OGRPoint ogrPoint; // Current point. ogrPoint.setX(CPLAtof(stgeom[1])); ogrPoint.setY(CPLAtof(stgeom[2])); OGRLineString *ogrLine = new OGRLineString(); ogrLine->addPoint(&ogrPoint); // Parse geometry. char **tokens = NULL; bool end = false; OGRCircularString *arc = NULL; //current arc while (!end && (tokens = ReadParseLine()) != NULL) { const char *firsttok = CSLGetField(tokens, 0); if( firsttok == NULL ) { // do nothing } else if (EQUAL(firsttok, "LIPT") && CSLCount(tokens) >= 3) { ogrPoint.setX(CPLAtof(tokens[1])); ogrPoint.setY(CPLAtof(tokens[2])); if (arc) { arc->addPoint(&ogrPoint); OGRErr error = ogrCurve->addCurveDirectly(arc); if (error != OGRERR_NONE) { char* pszJSon = arc->exportToJson(); CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s", pszJSon ? pszJSon : "(null)" ); CPLFree(pszJSon); delete arc; } arc = NULL; } ogrLine->addPoint(&ogrPoint); } else if (EQUAL(firsttok, "ARCP") && CSLCount(tokens) >= 3) { //Finish line and start arc if (ogrLine->getNumPoints() > 1) { OGRErr error = ogrCurve->addCurveDirectly(ogrLine); if (error != OGRERR_NONE) { char* pszJSon = ogrLine->exportToJson(); CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s", pszJSon ? pszJSon : "(null)" ); CPLFree(pszJSon); delete ogrLine; } ogrLine = new OGRLineString(); } else { ogrLine->empty(); } delete arc; arc = new OGRCircularString(); arc->addPoint(&ogrPoint); ogrPoint.setX(CPLAtof(tokens[1])); ogrPoint.setY(CPLAtof(tokens[2])); arc->addPoint(&ogrPoint); } else if (EQUAL(firsttok, "ELIN")) { if (ogrLine->getNumPoints() > 1) { // Ignore single LIPT after ARCP OGRErr error = ogrCurve->addCurveDirectly(ogrLine); if (error != OGRERR_NONE) { char* pszJSon = ogrLine->exportToJson(); CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s", pszJSon ? pszJSon : "(null)" ); CPLFree(pszJSon); delete ogrLine; } ogrLine = NULL; } if (!ogrCurve->IsEmpty()) { if (ogrMultiLine) { OGRErr error = ogrMultiLine->addGeometryDirectly(ogrCurve); if (error != OGRERR_NONE) { char* pszJSon = ogrCurve->exportToJson(); CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s", pszJSon ? pszJSon : "(null)" ); CPLFree(pszJSon); delete ogrCurve; } ogrCurve = NULL; } if (ogrPoly) { OGRErr error = ogrPoly->addRingDirectly(ogrCurve); if (error != OGRERR_NONE) { char* pszJSon = ogrCurve->exportToJson(); CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s", pszJSon ? pszJSon : "(null)" ); CPLFree(pszJSon); delete ogrCurve; } ogrCurve = NULL; } } end = true; } else if (EQUAL(firsttok, "EEDG")) { end = true; } else if (EQUAL(firsttok, "LATT")) { //Line Attributes (ignored) } else if (EQUAL(firsttok, "EFLA")) { end = true; } else if (EQUAL(firsttok, "ETAB")) { end = true; } else { CPLError( CE_Warning, CPLE_AppDefined, "Unexpected token: %s", firsttok ); } CSLDestroy(tokens); } delete arc; delete ogrLine; //Set feature geometry if (eType == wkbMultiCurve) { feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine); delete ogrCurve; } else if (eType == wkbMultiLineString) { feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine->getLinearGeometry()); delete ogrMultiLine; delete ogrCurve; } else if (eType == wkbCurvePolygon) { feature->SetGeomFieldDirectly(geomIdx, ogrPoly); delete ogrCurve; } else if (eType == wkbPolygon) { feature->SetGeomFieldDirectly(geomIdx, ogrPoly->getLinearGeometry()); delete ogrPoly; delete ogrCurve; } else { feature->SetGeomFieldDirectly(geomIdx, ogrCurve); } }
/*! \brief Set feature geometry Also checks if given geometry is valid \param poGeom pointer to OGRGeometry \param ftype geometry VFK type \return TRUE on valid feature or otherwise FALSE */ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype) { m_bGeometry = TRUE; delete m_paGeom; m_paGeom = NULL; m_bValid = TRUE; if (!poGeom) { return m_bValid; } /* check empty geometries */ if (m_nGeometryType == wkbNone && poGeom->IsEmpty()) { CPLError(CE_Warning, CPLE_AppDefined, "%s: empty geometry fid = " CPL_FRMT_GIB, m_poDataBlock->GetName(), m_nFID); m_bValid = FALSE; } /* check coordinates */ if (m_nGeometryType == wkbPoint) { double x, y; x = ((OGRPoint *) poGeom)->getX(); y = ((OGRPoint *) poGeom)->getY(); if (x > -430000 || x < -910000 || y > -930000 || y < -1230000) { CPLDebug("OGR-VFK", "%s: invalid point fid = " CPL_FRMT_GIB, m_poDataBlock->GetName(), m_nFID); m_bValid = FALSE; } } /* check degenerated polygons */ if (m_nGeometryType == wkbPolygon) { OGRLinearRing *poRing; poRing = ((OGRPolygon *) poGeom)->getExteriorRing(); if (!poRing || poRing->getNumPoints() < 3) { CPLDebug("OGR-VFK", "%s: invalid polygon fid = " CPL_FRMT_GIB, m_poDataBlock->GetName(), m_nFID); m_bValid = FALSE; } } if (m_bValid) { if (ftype) { OGRPoint pt; OGRGeometry *poGeomCurved; OGRCircularString poGeomString; poGeomCurved = NULL; if (EQUAL(ftype, "15") || EQUAL(ftype, "16")) { /* -> circle or arc */ int npoints; npoints = ((OGRLineString *) poGeom)->getNumPoints(); for (int i = 0; i < npoints; i++) { ((OGRLineString *) poGeom)->getPoint(i, &pt); poGeomString.addPoint(&pt); } if (EQUAL(ftype, "15")) { /* compute center and radius of a circle */ double x[3], y[3]; double m1, n1, m2, n2, c1, c2, mx; double c_x, c_y; for (int i = 0; i < npoints; i++) { ((OGRLineString *) poGeom)->getPoint(i, &pt); x[i] = pt.getX(); y[i] = pt.getY(); } m1 = (x[0] + x[1]) / 2.0; n1 = (y[0] + y[1]) / 2.0; m2 = (x[0] + x[2]) / 2.0; n2 = (y[0] + y[2]) / 2.0; c1 = (x[1] - x[0]) * m1 + (y[1] - y[0]) * n1; c2 = (x[2] - x[0]) * m2 + (y[2] - y[0]) * n2; mx = (x[1] - x[0]) * (y[2] - y[0]) + (y[1] - y[0]) * (x[0] - x[2]); c_x = (c1 * (y[2] - y[0]) + c2 * (y[0] - y[1])) / mx; c_y = (c1 * (x[0] - x[2]) + c2 * (x[1] - x[0])) / mx; /* compute a new intermediate point */ pt.setX(c_x - (x[1] - c_x)); pt.setY(c_y - (y[1] - c_y)); poGeomString.addPoint(&pt); /* add last point */ ((OGRLineString *) poGeom)->getPoint(0, &pt); poGeomString.addPoint(&pt); } } else if (strlen(ftype) > 2 && EQUALN(ftype, "15", 2)) { /* -> circle with radius */ float r; char s[3]; /* 15 */ r = 0; if (2 != sscanf(ftype, "%s %f", s, &r) || r < 0) { CPLDebug("OGR-VFK", "%s: invalid circle (unknown or negative radius) " "fid = " CPL_FRMT_GIB, m_poDataBlock->GetName(), m_nFID); m_bValid = FALSE; } else { double c_x, c_y; ((OGRLineString *) poGeom)->getPoint(0, &pt); c_x = pt.getX(); c_y = pt.getY(); /* define first point on a circle */ pt.setX(c_x + r); pt.setY(c_y); poGeomString.addPoint(&pt); /* define second point on a circle */ pt.setX(c_x); pt.setY(c_y + r); poGeomString.addPoint(&pt); /* define third point on a circle */ pt.setX(c_x - r); pt.setY(c_y); poGeomString.addPoint(&pt); /* define fourth point on a circle */ pt.setX(c_x); pt.setY(c_y - r); poGeomString.addPoint(&pt); /* define last point (=first) on a circle */ pt.setX(c_x + r); pt.setY(c_y); poGeomString.addPoint(&pt); } } else if (EQUAL(ftype, "11")) { /* curve */ int npoints; npoints = ((OGRLineString *) poGeom)->getNumPoints(); if (npoints > 2) { /* circular otherwise line string */ for (int i = 0; i < npoints; i++) { ((OGRLineString *) poGeom)->getPoint(i, &pt); poGeomString.addPoint(&pt); } } } if (!poGeomString.IsEmpty()) poGeomCurved = poGeomString.CurveToLine(); if (poGeomCurved) { int npoints; npoints = ((OGRLineString *) poGeomCurved)->getNumPoints(); CPLDebug("OGR-VFK", "%s: curve (type=%s) to linestring (npoints=%d) fid = " CPL_FRMT_GIB, m_poDataBlock->GetName(), ftype, npoints, m_nFID); if (npoints > 1) m_paGeom = (OGRGeometry *) poGeomCurved->clone(); delete poGeomCurved; } } if (!m_paGeom) { /* check degenerated linestrings */ if (m_nGeometryType == wkbLineString) { int npoints; npoints = ((OGRLineString *) poGeom)->getNumPoints(); if (npoints < 2) { CPLError(CE_Warning, CPLE_AppDefined, "%s: invalid linestring (%d vertices) fid = " CPL_FRMT_GIB, m_poDataBlock->GetName(), npoints, m_nFID); m_bValid = FALSE; } } if (m_bValid) m_paGeom = (OGRGeometry *) poGeom->clone(); /* make copy */ } } return m_bValid; }
void ILI1Reader::ReadGeom(char **stgeom, int geomIdx, OGRwkbGeometryType eType, OGRFeature *feature) { char **tokens = NULL; const char *firsttok = NULL; int end = FALSE; OGRCompoundCurve *ogrCurve = NULL; //current compound curve OGRLineString *ogrLine = NULL; //current line OGRCircularString *arc = NULL; //current arc OGRCurvePolygon *ogrPoly = NULL; //current polygon OGRPoint ogrPoint; //current point OGRMultiCurve *ogrMultiLine = NULL; //current multi line //CPLDebug( "OGR_ILI", "ILI1Reader::ReadGeom geomIdx: %d OGRGeometryType: %s", geomIdx, OGRGeometryTypeToName(eType)); if (eType == wkbNone) { CPLError(CE_Warning, CPLE_AppDefined, "Calling ILI1Reader::ReadGeom with wkbNone" ); } //Initialize geometry ogrCurve = new OGRCompoundCurve(); if (eType == wkbMultiCurve || eType == wkbMultiLineString) { ogrMultiLine = new OGRMultiCurve(); } else if (eType == wkbPolygon || eType == wkbCurvePolygon) { ogrPoly = new OGRCurvePolygon(); } //tokens = ["STPT", "1111", "22222"] ogrPoint.setX(CPLAtof(stgeom[1])); ogrPoint.setY(CPLAtof(stgeom[2])); ogrLine = new OGRLineString(); ogrLine->addPoint(&ogrPoint); //Parse geometry while (!end && (tokens = ReadParseLine())) { firsttok = CSLGetField(tokens, 0); if (EQUAL(firsttok, "LIPT")) { ogrPoint.setX(CPLAtof(tokens[1])); ogrPoint.setY(CPLAtof(tokens[2])); if (arc) { arc->addPoint(&ogrPoint); ogrCurve->addCurveDirectly(arc); arc = NULL; } ogrLine->addPoint(&ogrPoint); } else if (EQUAL(firsttok, "ARCP")) { //Finish line and start arc if (ogrLine->getNumPoints() > 1) { ogrCurve->addCurveDirectly(ogrLine); ogrLine = new OGRLineString(); } else { ogrLine->empty(); } arc = new OGRCircularString(); arc->addPoint(&ogrPoint); ogrPoint.setX(CPLAtof(tokens[1])); ogrPoint.setY(CPLAtof(tokens[2])); arc->addPoint(&ogrPoint); } else if (EQUAL(firsttok, "ELIN")) { if (!ogrLine->IsEmpty()) { ogrCurve->addCurveDirectly(ogrLine); } if (!ogrCurve->IsEmpty()) { if (ogrMultiLine) { ogrMultiLine->addGeometryDirectly(ogrCurve); } if (ogrPoly) { ogrPoly->addRingDirectly(ogrCurve); } } end = TRUE; } else if (EQUAL(firsttok, "EEDG")) { end = TRUE; } else if (EQUAL(firsttok, "LATT")) { //Line Attributes (ignored) } else if (EQUAL(firsttok, "EFLA")) { end = TRUE; } else if (EQUAL(firsttok, "ETAB")) { end = TRUE; } else { CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s", firsttok ); } CSLDestroy(tokens); } //Set feature geometry if (eType == wkbMultiCurve) { feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine); } else if (eType == wkbMultiLineString) { feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine->getLinearGeometry()); delete ogrMultiLine; } else if (eType == wkbCurvePolygon) { feature->SetGeomFieldDirectly(geomIdx, ogrPoly); } else if (eType == wkbPolygon) { feature->SetGeomFieldDirectly(geomIdx, ogrPoly->getLinearGeometry()); delete ogrPoly; } else { feature->SetGeomFieldDirectly(geomIdx, ogrCurve); } }
static OGRCompoundCurve *getPolyline(DOMElement *elem) { // elem -> POLYLINE OGRCompoundCurve *ogrCurve = new OGRCompoundCurve(); OGRLineString *ls = new OGRLineString(); DOMElement *lineElem = (DOMElement *)elem->getFirstChild(); while (lineElem != NULL) { char* pszTagName = XMLString::transcode(lineElem->getTagName()); if (cmpStr(ILI2_COORD, pszTagName) == 0) { OGRPoint* poPoint = getPoint(lineElem); ls->addPoint(poPoint); delete poPoint; } else if (cmpStr(ILI2_ARC, pszTagName) == 0) { //Finish line and start arc if (ls->getNumPoints() > 1) { ogrCurve->addCurveDirectly(ls); ls = new OGRLineString(); } else { ls->empty(); } OGRCircularString *arc = new OGRCircularString(); // end point OGRPoint *ptEnd = new OGRPoint(); // point on the arc OGRPoint *ptOnArc = new OGRPoint(); // radius // double radius = 0; DOMElement *arcElem = (DOMElement *)lineElem->getFirstChild(); while (arcElem != NULL) { char* pszTagName2 = XMLString::transcode(arcElem->getTagName()); char* pszObjValue = getObjValue(arcElem); if (cmpStr("C1", pszTagName2) == 0) ptEnd->setX(CPLAtof(pszObjValue)); else if (cmpStr("C2", pszTagName2) == 0) ptEnd->setY(CPLAtof(pszObjValue)); else if (cmpStr("C3", pszTagName2) == 0) ptEnd->setZ(CPLAtof(pszObjValue)); else if (cmpStr("A1", pszTagName2) == 0) ptOnArc->setX(CPLAtof(pszObjValue)); else if (cmpStr("A2", pszTagName2) == 0) ptOnArc->setY(CPLAtof(pszObjValue)); else if (cmpStr("A3", pszTagName2) == 0) ptOnArc->setZ(CPLAtof(pszObjValue)); else if (cmpStr("R", pszTagName2) == 0) { // radius = CPLAtof(pszObjValue); } CPLFree(pszObjValue); XMLString::release(&pszTagName2); arcElem = (DOMElement *)arcElem->getNextSibling(); } OGRPoint *ptStart = getPoint((DOMElement *)lineElem->getPreviousSibling()); // COORD or ARC arc->addPoint(ptStart); arc->addPoint(ptOnArc); arc->addPoint(ptEnd); ogrCurve->addCurveDirectly(arc); delete ptStart; delete ptEnd; delete ptOnArc; } /* else { // TODO: StructureValue in Polyline not yet supported } */ XMLString::release(&pszTagName); lineElem = (DOMElement *)lineElem->getNextSibling(); } if (ls->getNumPoints() > 1) { ogrCurve->addCurveDirectly(ls); } else { delete ls; } return ogrCurve; }
OGRFeature *OGRCADLayer::GetFeature( GIntBig nFID ) { if( poCADLayer.getGeometryCount() <= static_cast<size_t>(nFID) || nFID < 0 ) { return nullptr; } OGRFeature *poFeature = nullptr; CADGeometry *poCADGeometry = poCADLayer.getGeometry( static_cast<size_t>(nFID) ); if( nullptr == 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 nullptr; } 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() ); oCirclePoint1.setZ( stCircleCenter.getZ() ); poCircle->addPoint( &oCirclePoint1 ); OGRPoint oCirclePoint2; oCirclePoint2.setX( stCircleCenter.getX() ); oCirclePoint2.setY( stCircleCenter.getY() + poCADCircle->getRadius() ); oCirclePoint2.setZ( stCircleCenter.getZ() ); poCircle->addPoint( &oCirclePoint2 ); OGRPoint oCirclePoint3; oCirclePoint3.setX( stCircleCenter.getX() + poCADCircle->getRadius() ); oCirclePoint3.setY( stCircleCenter.getY() ); oCirclePoint3.setZ( stCircleCenter.getZ() ); poCircle->addPoint( &oCirclePoint3 ); OGRPoint oCirclePoint4; oCirclePoint4.setX( stCircleCenter.getX() ); oCirclePoint4.setY( stCircleCenter.getY() - poCADCircle->getRadius() ); oCirclePoint4.setZ( stCircleCenter.getZ() ); poCircle->addPoint( &oCirclePoint4 ); // 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 couldn't 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; std::vector< double > adfBulges = poCADLWPolyline->getBulges(); const size_t nCount = std::min(adfBulges.size(), poCADLWPolyline->getVertexCount()); for( size_t iCurrentVertex = 0; iCurrentVertex + 1 < nCount; iCurrentVertex++ ) { 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; if( dfH == 0.0 ) dfH = 1.0; // just to avoid a division by zero 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; /* * Tessellate 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 ); } } 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(); dfStartAngle = fmod(dfStartAngle, 360.0); dfEndAngle = fmod(dfEndAngle, 360.0); 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; }