Example #1
2
OGRFeature *OGRDWGLayer::TranslateDIMENSION( OdDbEntityPtr poEntity )

{
    OdDbDimensionPtr poDim = OdDbDimension::cast( poEntity );
    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );

    double dfHeight = CPLAtof(poDS->GetVariable("$DIMTXT", "2.5"));
    OdGePoint3d oTextPos, oTarget1, oTarget2, oArrow1;
    CPLString osText;

    TranslateGenericProperties( poFeature, poEntity );

/* -------------------------------------------------------------------- */
/*      Generic Dimension stuff.                                        */
/* -------------------------------------------------------------------- */
    osText = (const char *) poDim->dimensionText();

    oTextPos = poDim->textPosition();

/* -------------------------------------------------------------------- */
/*      Specific based on the subtype.                                  */
/* -------------------------------------------------------------------- */
    OdRxClass *poClass = poEntity->isA();
    const OdString osName = poClass->name();
    const char *pszEntityClassName = (const char *) osName;

    if( EQUAL(pszEntityClassName,"AcDbRotatedDimension") )
    {
        OdDbRotatedDimensionPtr poRDim = OdDbDimension::cast( poEntity );

        oTarget2 = poRDim->xLine1Point();
        oTarget1 = poRDim->xLine2Point();
        oArrow1 = poRDim->dimLinePoint();
    }

    else if( EQUAL(pszEntityClassName,"AcDbAlignedDimension") )
    {
        OdDbAlignedDimensionPtr poADim = OdDbDimension::cast( poEntity );

        oTarget2 = poADim->xLine1Point();
        oTarget1 = poADim->xLine2Point();
        oArrow1 = poADim->dimLinePoint();
    }

/*************************************************************************

   DIMENSION geometry layout

                  (11,21)(text center point)
        |          DimText                  |
(10,20) X<--------------------------------->X (Arrow2 - computed)
(Arrow1)|                                   |
        |                                   |
        |                                   X (13,23) (Target2)
        |
        X (14,24) (Target1)

Given:
  Locations Arrow1, Target1, and Target2 we need to compute Arrow2.

Steps:
 1) Compute direction vector from Target1 to Arrow1 (Vec1).
 2) Compute direction vector for arrow as perpendicular to Vec1 (call Vec2).
 3) Compute Arrow2 location as intersection between line defined by
    Vec2 and Arrow1 and line defined by Target2 and direction Vec1 (call Arrow2)

Then we can draw lines for the various components.

Note that Vec1 and Vec2 may be horizontal, vertical or on an angle but
the approach is as above in all these cases.

*************************************************************************/

/* -------------------------------------------------------------------- */
/*      Step 1, compute direction vector between Target1 and Arrow1.    */
/* -------------------------------------------------------------------- */
    double dfVec1X, dfVec1Y;

    dfVec1X = (oArrow1.x - oTarget1.x);
    dfVec1Y = (oArrow1.y - oTarget1.y);

/* -------------------------------------------------------------------- */
/*      Step 2, compute the direction vector from Arrow1 to Arrow2      */
/*      as a perpendicular to Vec1.                                     */
/* -------------------------------------------------------------------- */
    double dfVec2X, dfVec2Y;

    dfVec2X = dfVec1Y;
    dfVec2Y = -dfVec1X;

/* -------------------------------------------------------------------- */
/*      Step 3, compute intersection of line from target2 along         */
/*      direction vector 1, with the line through Arrow1 and            */
/*      direction vector 2.                                             */
/* -------------------------------------------------------------------- */
    double dfL1M, dfL1B, dfL2M, dfL2B;
    double dfArrowX2, dfArrowY2;

    // special case if vec1 is vertical.
    if( dfVec1X == 0.0 )
    {
        dfArrowX2 = oTarget2.x;
        dfArrowY2 = oArrow1.y;
    }

    // special case if vec2 is horizontal.
    else if( dfVec1Y == 0.0 )
    {
        dfArrowX2 = oArrow1.x;
        dfArrowY2 = oTarget2.y;
    }

    else // General case for diagonal vectors.
    {
        // first convert vec1 + target2 into y = mx + b format: call this L1

        dfL1M = dfVec1Y / dfVec1X;
        dfL1B = oTarget2.y - dfL1M * oTarget2.x;

        // convert vec2 + Arrow1 into y = mx + b format, call this L2

        dfL2M = dfVec2Y / dfVec2X;
        dfL2B = oArrow1.y - dfL2M * oArrow1.x;

        // Compute intersection x = (b2-b1) / (m1-m2)

        dfArrowX2 = (dfL2B - dfL1B) / (dfL1M-dfL2M);
        dfArrowY2 = dfL2M * dfArrowX2 + dfL2B;
    }

/* -------------------------------------------------------------------- */
/*      Compute the text angle.                                         */
/* -------------------------------------------------------------------- */
    double dfAngle = atan2(dfVec2Y,dfVec2X) * 180.0 / M_PI;

/* -------------------------------------------------------------------- */
/*      Rescale the direction vectors so we can use them in             */
/*      constructing arrowheads.  We want them to be about 3% of the    */
/*      length of line on which the arrows will be drawn.               */
/* -------------------------------------------------------------------- */
#define VECTOR_LEN(x,y) sqrt( (x)*(x) + (y)*(y) )
#define POINT_DIST(x1,y1,x2,y2)  VECTOR_LEN((x2-x1),(y2-y1))

    double dfBaselineLength = POINT_DIST(oArrow1.x,oArrow1.y,
                                         dfArrowX2,dfArrowY2);
    double dfTargetLength = dfBaselineLength * 0.03;
    double dfScaleFactor;

    // recompute vector 2 to ensure the direction is regular
    dfVec2X = (dfArrowX2 - oArrow1.x);
    dfVec2Y = (dfArrowY2 - oArrow1.y);

    // vector 1
    dfScaleFactor = dfTargetLength / VECTOR_LEN(dfVec1X,dfVec1Y);
    dfVec1X *= dfScaleFactor;
    dfVec1Y *= dfScaleFactor;

    // vector 2
    dfScaleFactor = dfTargetLength / VECTOR_LEN(dfVec2X,dfVec2Y);
    dfVec2X *= dfScaleFactor;
    dfVec2Y *= dfScaleFactor;

/* -------------------------------------------------------------------- */
/*      Create geometries for the different components of the           */
/*      dimension object.                                               */
/* -------------------------------------------------------------------- */
    OGRMultiLineString *poMLS = new OGRMultiLineString();
    OGRLineString oLine;

    // main arrow line between Arrow1 and Arrow2
    oLine.setPoint( 0, oArrow1.x, oArrow1.y );
    oLine.setPoint( 1, dfArrowX2, dfArrowY2 );
    poMLS->addGeometry( &oLine );

    // dimension line from Target1 to Arrow1 with a small extension.
    oLine.setPoint( 0, oTarget1.x, oTarget1.y );
    oLine.setPoint( 1, oArrow1.x + dfVec1X, oArrow1.y + dfVec1Y );
    poMLS->addGeometry( &oLine );

    // dimension line from Target2 to Arrow2 with a small extension.
    oLine.setPoint( 0, oTarget2.x, oTarget2.y );
    oLine.setPoint( 1, dfArrowX2 + dfVec1X, dfArrowY2 + dfVec1Y );
    poMLS->addGeometry( &oLine );

    // add arrow1 arrow head.

    oLine.setPoint( 0, oArrow1.x, oArrow1.y );
    oLine.setPoint( 1,
                    oArrow1.x + dfVec2X*3 + dfVec1X,
                    oArrow1.y + dfVec2Y*3 + dfVec1Y );
    poMLS->addGeometry( &oLine );

    oLine.setPoint( 0, oArrow1.x, oArrow1.y );
    oLine.setPoint( 1,
                    oArrow1.x + dfVec2X*3 - dfVec1X,
                    oArrow1.y + dfVec2Y*3 - dfVec1Y );
    poMLS->addGeometry( &oLine );

    // add arrow2 arrow head.

    oLine.setPoint( 0, dfArrowX2, dfArrowY2 );
    oLine.setPoint( 1,
                    dfArrowX2 - dfVec2X*3 + dfVec1X,
                    dfArrowY2 - dfVec2Y*3 + dfVec1Y );
    poMLS->addGeometry( &oLine );

    oLine.setPoint( 0, dfArrowX2, dfArrowY2 );
    oLine.setPoint( 1,
                    dfArrowX2 - dfVec2X*3 - dfVec1X,
                    dfArrowY2 - dfVec2Y*3 - dfVec1Y );
    poMLS->addGeometry( &oLine );

    poFeature->SetGeometryDirectly( poMLS );

    PrepareLineStyle( poFeature );

/* -------------------------------------------------------------------- */
/*      Is the layer disabled/hidden/frozen/off?                        */
/* -------------------------------------------------------------------- */
    CPLString osLayer = poFeature->GetFieldAsString("Layer");

    int bHidden =
        EQUAL(poDS->LookupLayerProperty( osLayer, "Hidden" ), "1");

/* -------------------------------------------------------------------- */
/*      Work out the color for this feature.                            */
/* -------------------------------------------------------------------- */
    int nColor = 256;

    if( oStyleProperties.count("Color") > 0 )
        nColor = atoi(oStyleProperties["Color"]);

    // Use layer color?
    if( nColor < 1 || nColor > 255 )
    {
        const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
        if( pszValue != NULL )
            nColor = atoi(pszValue);
    }

    if( nColor < 1 || nColor > 255 )
        nColor = 8;

/* -------------------------------------------------------------------- */
/*      Prepare a new feature to serve as the dimension text label      */
/*      feature.  We will push it onto the layer as a pending           */
/*      feature for the next feature read.                              */
/* -------------------------------------------------------------------- */

    // a single space suppresses labeling.
    if( osText == " " )
        return poFeature;

    OGRFeature *poLabelFeature = poFeature->Clone();

    poLabelFeature->SetGeometryDirectly( new OGRPoint( oTextPos.x, oTextPos.y ) );

    // Do we need to compute the dimension value?
    if( osText.empty() )
    {
        FormatDimension( osText, POINT_DIST( oArrow1.x, oArrow1.y,
                                             dfArrowX2, dfArrowY2 ) );
    }

    CPLString osStyle;
    char szBuffer[64];
    char* pszComma = NULL;

    osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\",p:5",osText.c_str());

    if( dfAngle != 0.0 )
    {
        CPLsnprintf(szBuffer, sizeof(szBuffer), "%.3g", dfAngle);
        pszComma = strchr(szBuffer, ',');
        if (pszComma)
            *pszComma = '.';
        osStyle += CPLString().Printf(",a:%s", szBuffer);
    }

    if( dfHeight != 0.0 )
    {
        CPLsnprintf(szBuffer, sizeof(szBuffer), "%.3g", dfHeight);
        pszComma = strchr(szBuffer, ',');
        if (pszComma)
            *pszComma = '.';
        osStyle += CPLString().Printf(",s:%sg", szBuffer);
    }

    const unsigned char *pabyDWGColors = ACGetColorTable();

    snprintf( szBuffer, sizeof(szBuffer), ",c:#%02x%02x%02x",
              pabyDWGColors[nColor*3+0],
              pabyDWGColors[nColor*3+1],
              pabyDWGColors[nColor*3+2] );
    osStyle += szBuffer;

    if( bHidden )
        osStyle += "00";

    osStyle += ")";

    poLabelFeature->SetStyleString( osStyle );

    apoPendingFeatures.push( poLabelFeature );

    return poFeature;
}
OGRFeature *OGROpenAirLabelLayer::GetNextRawFeature()
{
    const char* pszLine;
    double dfLat = 0, dfLon = 0;
    int bHasCoord = FALSE;

    while(TRUE)
    {
        pszLine = CPLReadLine2L(fpOpenAir, 1024, NULL);
        if (pszLine == NULL)
            return NULL;

        if (pszLine[0] == '*' || pszLine[0] == '\0')
            continue;

        if (EQUALN(pszLine, "AC ", 3))
        {
            if (osCLASS.size() != 0)
            {
                osNAME = "";
                osCEILING = "";
                osFLOOR = "";
            }
            osCLASS = pszLine + 3;
        }
        else if (EQUALN(pszLine, "AN ", 3))
            osNAME = pszLine + 3;
        else if (EQUALN(pszLine, "AH ", 3))
            osCEILING = pszLine + 3;
        else if (EQUALN(pszLine, "AL ", 3))
            osFLOOR = pszLine + 3;
        else if (EQUALN(pszLine, "AT ", 3))
        {
            bHasCoord = OGROpenAirGetLatLon(pszLine + 3, dfLat, dfLon);
            break;
        }
    }

    OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
    poFeature->SetField(0, osCLASS.c_str());
    poFeature->SetField(1, osNAME.c_str());
    poFeature->SetField(2, osFLOOR.c_str());
    poFeature->SetField(3, osCEILING.c_str());

    CPLString osStyle;
    osStyle.Printf("LABEL(t:\"%s\")", osNAME.c_str());
    poFeature->SetStyleString(osStyle.c_str());

    if (bHasCoord)
    {
        OGRPoint* poPoint = new OGRPoint(dfLon, dfLat);
        poPoint->assignSpatialReference(poSRS);
        poFeature->SetGeometryDirectly(poPoint);
    }

    poFeature->SetFID(nNextFID++);

    return poFeature;
}
Example #3
0
OGRFeature *OGROpenAirLayer::GetNextRawFeature()
{
    const char* pszLine;
    CPLString osCLASS, osNAME, osFLOOR, osCEILING;
    OGRLinearRing oLR;
    /* double dfLastLat = 0, dfLastLon = 0; */
    int bFirst = TRUE;
    int bClockWise = TRUE;
    double dfCenterLat = 0, dfCenterLon = 0;
    int bHasCenter = FALSE;
    OpenAirStyle sStyle;
    sStyle.penStyle = -1;
    sStyle.penWidth = -1;
    sStyle.penR = sStyle.penG = sStyle.penB = -1;
    sStyle.fillR = sStyle.fillG = sStyle.fillB = -1;

    if (bEOF)
        return NULL;

    while(TRUE)
    {
        if (bFirst && bHasLastLine)
        {
            pszLine = osLastLine.c_str();
            bFirst = FALSE;
        }
        else
        {
            pszLine = CPLReadLine2L(fpOpenAir, 1024, NULL);
            if (pszLine == NULL)
            {
                bEOF = TRUE;
                if (oLR.getNumPoints() == 0)
                    return NULL;

                if (osCLASS.size() != 0 &&
                    oStyleMap.find(osCLASS) != oStyleMap.end())
                {
                    memcpy(&sStyle, oStyleMap[osCLASS], sizeof(sStyle));
                }
                break;
            }
            osLastLine = pszLine;
            bHasLastLine = TRUE;
        }

        if (pszLine[0] == '*' || pszLine[0] == '\0')
            continue;

        if (EQUALN(pszLine, "AC ", 3) || EQUALN(pszLine, "AC,", 3))
        {
            if (osCLASS.size() != 0)
            {
                if (sStyle.penStyle != -1 || sStyle.fillR != -1)
                {
                    if (oLR.getNumPoints() == 0)
                    {
                        OpenAirStyle* psStyle;
                        if (oStyleMap.find(osCLASS) == oStyleMap.end())
                        {
                            psStyle = (OpenAirStyle*)CPLMalloc(
                                                    sizeof(OpenAirStyle));
                            oStyleMap[osCLASS] = psStyle;
                        }
                        else
                            psStyle = oStyleMap[osCLASS];
                        memcpy(psStyle, &sStyle, sizeof(sStyle));
                    }
                    else
                        break;
                }
                else if (oStyleMap.find(osCLASS) != oStyleMap.end())
                {
                    memcpy(&sStyle, oStyleMap[osCLASS], sizeof(sStyle));
                    break;
                }
                else
                    break;
            }
            sStyle.penStyle = -1;
            sStyle.penWidth = -1;
            sStyle.penR = sStyle.penG = sStyle.penB = -1;
            sStyle.fillR = sStyle.fillG = sStyle.fillB = -1;
            osCLASS = pszLine + 3;
            bClockWise = TRUE;
            bHasCenter = FALSE;
        }
        else if (EQUALN(pszLine, "AN ", 3))
        {
            if (osNAME.size() != 0)
                break;
            osNAME = pszLine + 3;
        }
        else if (EQUALN(pszLine, "AH ", 3))
            osCEILING = pszLine + 3;
        else if (EQUALN(pszLine, "AL ", 3))
            osFLOOR = pszLine + 3;
        else if (EQUALN(pszLine, "AT ", 3))
        {
            /* Ignored for that layer*/
        }
        else if (EQUALN(pszLine, "SP ", 3))
        {
            if (osCLASS.size() != 0)
            {
                char** papszTokens = CSLTokenizeString2(pszLine+3, ", ", 0);
                if (CSLCount(papszTokens) == 5)
                {
                    sStyle.penStyle = atoi(papszTokens[0]);
                    sStyle.penWidth = atoi(papszTokens[1]);
                    sStyle.penR = atoi(papszTokens[2]);
                    sStyle.penG = atoi(papszTokens[3]);
                    sStyle.penB = atoi(papszTokens[4]);
                }
                CSLDestroy(papszTokens);
            }
        }
        else if (EQUALN(pszLine, "SB ", 3))
        {
            if (osCLASS.size() != 0)
            {
                char** papszTokens = CSLTokenizeString2(pszLine+3, ", ", 0);
                if (CSLCount(papszTokens) == 3)
                {
                    sStyle.fillR = atoi(papszTokens[0]);
                    sStyle.fillG = atoi(papszTokens[1]);
                    sStyle.fillB = atoi(papszTokens[2]);
                }
                CSLDestroy(papszTokens);
            }
        }
        else if (EQUALN(pszLine, "DP ", 3))
        {
            pszLine += 3;

            double dfLat, dfLon;
            if (!OGROpenAirGetLatLon(pszLine, dfLat, dfLon))
                continue;

            oLR.addPoint(dfLon, dfLat);
            /* dfLastLat = dfLat; */
            /* dfLastLon = dfLon; */
        }
        else if (EQUALN(pszLine, "DA ", 3))
        {
            pszLine += 3;

            char* pszStar = strchr((char*)pszLine, '*');
            if (pszStar) *pszStar = 0;
            char** papszTokens = CSLTokenizeString2(pszLine, ",", 0);
            if (bHasCenter && CSLCount(papszTokens) == 3)
            {
                double dfRadius = CPLAtof(papszTokens[0]) * 1852;
                double dfStartAngle = CPLAtof(papszTokens[1]);
                double dfEndAngle = CPLAtof(papszTokens[2]);

                if (bClockWise && dfEndAngle < dfStartAngle)
                    dfEndAngle += 360;
                else if (!bClockWise && dfStartAngle < dfEndAngle)
                    dfEndAngle -= 360;

                double dfStartDistance = dfRadius;
                double dfEndDistance = dfRadius;
                int nSign = (bClockWise) ? 1 : -1;
                double dfAngle;
                double dfLat, dfLon;
                for(dfAngle = dfStartAngle;
                    (dfAngle - dfEndAngle) * nSign < 0;
                    dfAngle += nSign)
                {
                    double pct = (dfAngle - dfStartAngle) /
                                    (dfEndAngle - dfStartAngle);
                    double dfDist = dfStartDistance * (1-pct) +
                                                        dfEndDistance * pct;
                    OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon,
                                             dfDist, dfAngle, &dfLat, &dfLon);
                    oLR.addPoint(dfLon, dfLat);
                }
                OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon,
                                         dfEndDistance, dfEndAngle, &dfLat, &dfLon);
                oLR.addPoint(dfLon, dfLat);

                /* dfLastLat = oLR.getY(oLR.getNumPoints() - 1); */
                /* dfLastLon = oLR.getX(oLR.getNumPoints() - 1); */
            }
            CSLDestroy(papszTokens);
        }
        else if (EQUALN(pszLine, "DB ", 3))
        {
            pszLine += 3;

            char* pszStar = strchr((char*)pszLine, '*');
            if (pszStar) *pszStar = 0;
            char** papszTokens = CSLTokenizeString2(pszLine, ",", 0);
            double dfFirstLat, dfFirstLon;
            double dfSecondLat, dfSecondLon;
            if (bHasCenter && CSLCount(papszTokens) == 2 &&
                OGROpenAirGetLatLon(papszTokens[0], dfFirstLat, dfFirstLon) &&
                OGROpenAirGetLatLon(papszTokens[1], dfSecondLat, dfSecondLon))
            {
                double dfStartDistance =OGRXPlane_Distance(dfCenterLat,
                        dfCenterLon, dfFirstLat, dfFirstLon);
                double dfEndDistance = OGRXPlane_Distance(dfCenterLat,
                        dfCenterLon, dfSecondLat, dfSecondLon);
                double dfStartAngle = OGRXPlane_Track(dfCenterLat,
                        dfCenterLon, dfFirstLat, dfFirstLon);
                double dfEndAngle = OGRXPlane_Track(dfCenterLat,
                        dfCenterLon, dfSecondLat, dfSecondLon);

                if (bClockWise && dfEndAngle < dfStartAngle)
                    dfEndAngle += 360;
                else if (!bClockWise && dfStartAngle < dfEndAngle)
                    dfEndAngle -= 360;

                int nSign = (bClockWise) ? 1 : -1;
                double dfAngle;
                for(dfAngle = dfStartAngle;
                    (dfAngle - dfEndAngle) * nSign < 0;
                    dfAngle += nSign)
                {
                    double dfLat, dfLon;
                    double pct = (dfAngle - dfStartAngle) /
                                    (dfEndAngle - dfStartAngle);
                    double dfDist = dfStartDistance * (1-pct) +
                                                    dfEndDistance * pct;
                    OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon,
                                             dfDist, dfAngle, &dfLat, &dfLon);
                    oLR.addPoint(dfLon, dfLat);
                }
                oLR.addPoint(dfSecondLon, dfSecondLat);

                /* dfLastLat = oLR.getY(oLR.getNumPoints() - 1); */
                /* dfLastLon = oLR.getX(oLR.getNumPoints() - 1); */
            }
            CSLDestroy(papszTokens);
        }
        else if ((EQUALN(pszLine, "DC ", 3) || EQUALN(pszLine, "DC=", 3)) &&
                 (bHasCenter || strstr(pszLine, "V X=") != NULL))
        {
            if (!bHasCenter)
            {
                const char* pszVX = strstr(pszLine, "V X=");
                bHasCenter = OGROpenAirGetLatLon(pszVX, dfCenterLat, dfCenterLon);
            }
            if (bHasCenter)
            {
                pszLine += 3;

                double dfRADIUS = CPLAtof(pszLine) * 1852;

                double dfAngle;
                double dfLat, dfLon;
                for(dfAngle = 0; dfAngle < 360; dfAngle += 1)
                {
                    OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon,
                                             dfRADIUS, dfAngle, &dfLat, &dfLon);
                    oLR.addPoint(dfLon, dfLat);
                }
                OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon,
                                         dfRADIUS, 0, &dfLat, &dfLon);
                oLR.addPoint(dfLon, dfLat);

                /* dfLastLat = oLR.getY(oLR.getNumPoints() - 1); */
                /* dfLastLon = oLR.getX(oLR.getNumPoints() - 1); */
            }
        }
        else if (EQUALN(pszLine, "V X=", 4))
        {
            bHasCenter =
                    OGROpenAirGetLatLon(pszLine + 4, dfCenterLat, dfCenterLon);
        }
        else if (EQUALN(pszLine, "V D=-", 5))
        {
            bClockWise = FALSE;
        }
        else if (EQUALN(pszLine, "V D=+", 5))
        {
            bClockWise = TRUE;
        }
        else
        {
            //CPLDebug("OpenAir", "Unexpected content : %s", pszLine);
        }
    }

    OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
    poFeature->SetField(0, osCLASS.c_str());
    poFeature->SetField(1, osNAME.c_str());
    poFeature->SetField(2, osFLOOR.c_str());
    poFeature->SetField(3, osCEILING.c_str());

    if (sStyle.penStyle != -1 || sStyle.fillR != -1)
    {
        CPLString osStyle;
        if (sStyle.penStyle != -1)
        {
            osStyle += CPLString().Printf("PEN(c:#%02X%02X%02X,w:%dpt",
                                 sStyle.penR, sStyle.penG, sStyle.penB,
                                 sStyle.penWidth);
            if (sStyle.penStyle == 1)
                osStyle += ",p:\"5px 5px\"";
            osStyle += ")";
        }
        if (sStyle.fillR != -1)
        {
            if (osStyle.size() != 0)
                osStyle += ";";
            osStyle += CPLString().Printf("BRUSH(fc:#%02X%02X%02X)",
                                 sStyle.fillR, sStyle.fillG, sStyle.fillB);
        }
        else
        {
            if (osStyle.size() != 0)
                osStyle += ";";
            osStyle += "BRUSH(fc:#00000000,id:\"ogr-brush-1\")";
        }
        if (osStyle.size() != 0)
            poFeature->SetStyleString(osStyle);
    }

    OGRPolygon* poPoly = new OGRPolygon();
    oLR.closeRings();
    poPoly->addRing(&oLR);
    poPoly->assignSpatialReference(poSRS);
    poFeature->SetGeometryDirectly(poPoly);
    poFeature->SetFID(nNextFID++);

    return poFeature;
}
Example #4
0
OGRFeature *OGRDWGLayer::TranslateHATCH( OdDbEntityPtr poEntity )

{
    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
    OdDbHatchPtr poHatch = OdDbHatch::cast( poEntity );
    OGRGeometryCollection oGC;

    TranslateGenericProperties( poFeature, poEntity );

    poFeature->SetField( "Text", 
                         (const char *) poHatch->patternName() );

/* -------------------------------------------------------------------- */
/*      Collect the loops.                                              */
/* -------------------------------------------------------------------- */
    for( int i = 0; i < poHatch->numLoops(); i++ )
    {
        DWGCollectBoundaryLoop( poHatch, i, &oGC );
    }

/* -------------------------------------------------------------------- */
/*      Try to turn the set of lines into something useful.             */
/* -------------------------------------------------------------------- */
    OGRErr eErr;

    OGRGeometryH hFinalGeom = 
        OGRBuildPolygonFromEdges( (OGRGeometryH) &oGC,
                                  TRUE, TRUE, 0.0000001, &eErr );

    poFeature->SetGeometryDirectly( (OGRGeometry *) hFinalGeom );

/* -------------------------------------------------------------------- */
/*      Work out the color for this feature.  For now we just assume    */
/*      solid fill.  We cannot trivially translate the various sorts    */
/*      of hatching.                                                    */
/* -------------------------------------------------------------------- */
    CPLString osLayer = poFeature->GetFieldAsString("Layer");

    int nColor = 256;

    if( oStyleProperties.count("Color") > 0 )
        nColor = atoi(oStyleProperties["Color"]);

    // Use layer color? 
    if( nColor < 1 || nColor > 255 )
    {
        const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
        if( pszValue != NULL )
            nColor = atoi(pszValue);
    }
        
/* -------------------------------------------------------------------- */
/*      Setup the style string.                                         */
/* -------------------------------------------------------------------- */
    if( nColor >= 1 && nColor <= 255 )
    {
        CPLString osStyle;
        const unsigned char *pabyDWGColors = ACGetColorTable();
        
        osStyle.Printf( "BRUSH(fc:#%02x%02x%02x)",
                        pabyDWGColors[nColor*3+0],
                        pabyDWGColors[nColor*3+1],
                        pabyDWGColors[nColor*3+2] );
        
        poFeature->SetStyleString( osStyle );
    }

    return poFeature;
}
OGRFeature *OGRDXFLayer::TranslateHATCH()

{
    char szLineBuf[257];
    int nCode;
    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );

    CPLString osHatchPattern;
    int nFillFlag = 0;
    OGRGeometryCollection oGC;

    while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
    {
        switch( nCode )
        {
          case 70:
            nFillFlag = atoi(szLineBuf);
            break;

          case 2:
            osHatchPattern = szLineBuf;
            poFeature->SetField( "Text", osHatchPattern.c_str() );
            break;

          case 91:
          {
              int nBoundaryPathCount = atoi(szLineBuf);
              int iBoundary;

              for( iBoundary = 0; iBoundary < nBoundaryPathCount; iBoundary++ )
              {
                  if (CollectBoundaryPath( &oGC ) != OGRERR_NONE)
                      break;
              }
          }
          break;

          default:
            TranslateGenericProperty( poFeature, nCode, szLineBuf );
            break;
        }
    }

    if( nCode == 0 )
        poDS->UnreadValue();

/* -------------------------------------------------------------------- */
/*      Try to turn the set of lines into something useful.             */
/* -------------------------------------------------------------------- */
    OGRErr eErr;

    OGRGeometry* poFinalGeom = (OGRGeometry *)
        OGRBuildPolygonFromEdges( (OGRGeometryH) &oGC,
                                  TRUE, TRUE, 0.0000001, &eErr );
    if( eErr != OGRERR_NONE )
    {
        delete poFinalGeom;
        OGRMultiLineString* poMLS = new OGRMultiLineString();
        for(int i=0;i<oGC.getNumGeometries();i++)
            poMLS->addGeometry(oGC.getGeometryRef(i));
        poFinalGeom = poMLS;
    }

    ApplyOCSTransformer( poFinalGeom );
    poFeature->SetGeometryDirectly( poFinalGeom );

/* -------------------------------------------------------------------- */
/*      Work out the color for this feature.  For now we just assume    */
/*      solid fill.  We cannot trivially translate the various sorts    */
/*      of hatching.                                                    */
/* -------------------------------------------------------------------- */
    CPLString osLayer = poFeature->GetFieldAsString("Layer");

    int nColor = 256;

    if( oStyleProperties.count("Color") > 0 )
        nColor = atoi(oStyleProperties["Color"]);

    // Use layer color? 
    if( nColor < 1 || nColor > 255 )
    {
        const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
        if( pszValue != NULL )
            nColor = atoi(pszValue);
    }
        
/* -------------------------------------------------------------------- */
/*      Setup the style string.                                         */
/* -------------------------------------------------------------------- */
    if( nColor >= 1 && nColor <= 255 )
    {
        CPLString osStyle;
        const unsigned char *pabyDXFColors = ACGetColorTable();
        
        osStyle.Printf( "BRUSH(fc:#%02x%02x%02x)",
                        pabyDXFColors[nColor*3+0],
                        pabyDXFColors[nColor*3+1],
                        pabyDXFColors[nColor*3+2] );
        
        poFeature->SetStyleString( osStyle );
    }

    return poFeature;
}
Example #6
0
OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )

{
    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );

    poFeature->SetFID( psElement->element_id );
    poFeature->SetField( "Type", psElement->type );
    poFeature->SetField( "Level", psElement->level );
    poFeature->SetField( "GraphicGroup", psElement->graphic_group );
    poFeature->SetField( "ColorIndex", psElement->color );
    poFeature->SetField( "Weight", psElement->weight );
    poFeature->SetField( "Style", psElement->style );
    

    m_nFeaturesRead++;

/* -------------------------------------------------------------------- */
/*      Collect linkage information                                     */
/* -------------------------------------------------------------------- */
#define MAX_LINK 100    
    int anEntityNum[MAX_LINK], anMSLink[MAX_LINK];
    unsigned char *pabyData;
    int iLink=0, nLinkCount=0;

    anEntityNum[0] = 0;
    anMSLink[0] = 0;

    pabyData = DGNGetLinkage( hDGN, psElement, iLink, NULL, 
                              anEntityNum+iLink, anMSLink+iLink, NULL );
    while( pabyData && nLinkCount < MAX_LINK )
    {
        iLink++;

        if( anEntityNum[nLinkCount] != 0 || anMSLink[nLinkCount] != 0 )
            nLinkCount++;

        anEntityNum[nLinkCount] = 0;
        anMSLink[nLinkCount] = 0;

        pabyData = DGNGetLinkage( hDGN, psElement, iLink, NULL, 
                                  anEntityNum+nLinkCount, anMSLink+nLinkCount, 
                                  NULL );
    }

/* -------------------------------------------------------------------- */
/*      Apply attribute linkage to feature.                             */
/* -------------------------------------------------------------------- */
    if( nLinkCount > 0 )
    {
        if( EQUAL(pszLinkFormat,"FIRST") )
        {
            poFeature->SetField( "EntityNum", anEntityNum[0] );
            poFeature->SetField( "MSLink", anMSLink[0] );
        }
        else if( EQUAL(pszLinkFormat,"LIST") )
        {
            poFeature->SetField( "EntityNum", nLinkCount, anEntityNum );
            poFeature->SetField( "MSLink", nLinkCount, anMSLink );
        }
        else if( EQUAL(pszLinkFormat,"STRING") )
        {
            char szEntityList[MAX_LINK*9], szMSLinkList[MAX_LINK*9];
            int nEntityLen = 0, nMSLinkLen = 0;

            for( iLink = 0; iLink < nLinkCount; iLink++ )
            {
                if( iLink != 0 )
                {
                    szEntityList[nEntityLen++] = ',';
                    szMSLinkList[nMSLinkLen++] = ',';
                }

                sprintf( szEntityList + nEntityLen, "%d", anEntityNum[iLink]);
                sprintf( szMSLinkList + nMSLinkLen, "%d", anMSLink[iLink] );
                
                nEntityLen += strlen(szEntityList + nEntityLen );
                nMSLinkLen += strlen(szMSLinkList + nMSLinkLen );
            }

            poFeature->SetField( "EntityNum", szEntityList );
            poFeature->SetField( "MSLink", szMSLinkList );
        }
    }

/* -------------------------------------------------------------------- */
/*      Lookup color.                                                   */
/* -------------------------------------------------------------------- */
    char        gv_color[128];
    int         gv_red, gv_green, gv_blue;
    char        szFSColor[128], szPen[256];

    szFSColor[0] = '\0';
    if( DGNLookupColor( hDGN, psElement->color, 
                        &gv_red, &gv_green, &gv_blue ) )
    {
        sprintf( gv_color, "%f %f %f 1.0", 
                 gv_red / 255.0, gv_green / 255.0, gv_blue / 255.0 );

        sprintf( szFSColor, "c:#%02x%02x%02x", 
                 gv_red, gv_green, gv_blue );
    }

/* -------------------------------------------------------------------- */
/*      Generate corresponding PEN style.                               */
/* -------------------------------------------------------------------- */
    if( psElement->style == DGNS_SOLID )
        sprintf( szPen, "PEN(id:\"ogr-pen-0\"" );
    else if( psElement->style == DGNS_DOTTED )
        sprintf( szPen, "PEN(id:\"ogr-pen-5\"" );
    else if( psElement->style == DGNS_MEDIUM_DASH )
        sprintf( szPen, "PEN(id:\"ogr-pen-2\"" );
    else if( psElement->style == DGNS_LONG_DASH )
        sprintf( szPen, "PEN(id:\"ogr-pen-4\"" );
    else if( psElement->style == DGNS_DOT_DASH )
        sprintf( szPen, "PEN(id:\"ogr-pen-6\"" );
    else if( psElement->style == DGNS_SHORT_DASH )
        sprintf( szPen, "PEN(id:\"ogr-pen-3\"" );
    else if( psElement->style == DGNS_DASH_DOUBLE_DOT )
        sprintf( szPen, "PEN(id:\"ogr-pen-7\"" );
    else if( psElement->style == DGNS_LONG_DASH_SHORT_DASH )
        sprintf( szPen, "PEN(p:\"10px 5px 4px 5px\"" );
    else
        sprintf( szPen, "PEN(id:\"ogr-pen-0\"" );

    if( strlen(szFSColor) > 0 )
        sprintf( szPen+strlen(szPen), ",%s", szFSColor );

    if( psElement->weight > 1 )
        sprintf( szPen+strlen(szPen), ",w:%dpx", psElement->weight );
        
    strcat( szPen, ")" );

    switch( psElement->stype )
    {
      case DGNST_MULTIPOINT:
        if( psElement->type == DGNT_SHAPE )
        {
            OGRLinearRing       *poLine = new OGRLinearRing();
            OGRPolygon          *poPolygon = new OGRPolygon();
            DGNElemMultiPoint *psEMP = (DGNElemMultiPoint *) psElement;
            
            poLine->setNumPoints( psEMP->num_vertices );
            for( int i = 0; i < psEMP->num_vertices; i++ )
            {
                poLine->setPoint( i, 
                                  psEMP->vertices[i].x,
                                  psEMP->vertices[i].y,
                                  psEMP->vertices[i].z );
            }

            poPolygon->addRingDirectly( poLine );

            poFeature->SetGeometryDirectly( poPolygon );

            ConsiderBrush( psElement, szPen, poFeature );
        }
        else if( psElement->type == DGNT_CURVE )
        {
            DGNElemMultiPoint *psEMP = (DGNElemMultiPoint *) psElement;
            OGRLineString       *poLine = new OGRLineString();
            DGNPoint            *pasPoints;
            int                 nPoints;

            nPoints = 5 * psEMP->num_vertices;
            pasPoints = (DGNPoint *) CPLMalloc(sizeof(DGNPoint) * nPoints);
            
            DGNStrokeCurve( hDGN, psEMP, nPoints, pasPoints );

            poLine->setNumPoints( nPoints );
            for( int i = 0; i < nPoints; i++ )
            {
                poLine->setPoint( i, 
                                  pasPoints[i].x,
                                  pasPoints[i].y,
                                  pasPoints[i].z );
            }

            poFeature->SetGeometryDirectly( poLine );
            CPLFree( pasPoints );

            poFeature->SetStyleString( szPen );
        }
        else
        {
            OGRLineString       *poLine = new OGRLineString();
            DGNElemMultiPoint *psEMP = (DGNElemMultiPoint *) psElement;
            
            if( psEMP->num_vertices > 0 )
            {
                poLine->setNumPoints( psEMP->num_vertices );
                for( int i = 0; i < psEMP->num_vertices; i++ )
                {
                    poLine->setPoint( i, 
                                      psEMP->vertices[i].x,
                                      psEMP->vertices[i].y,
                                      psEMP->vertices[i].z );
                }
                
                poFeature->SetGeometryDirectly( poLine );
            }

            poFeature->SetStyleString( szPen );
        }
        break;

      case DGNST_ARC:
      {
          OGRLineString *poLine = new OGRLineString();
          DGNElemArc    *psArc = (DGNElemArc *) psElement;
          DGNPoint      asPoints[90];
          int           nPoints;

          nPoints = (int) (MAX(1,ABS(psArc->sweepang) / 5) + 1);
          DGNStrokeArc( hDGN, psArc, nPoints, asPoints );

          poLine->setNumPoints( nPoints );
          for( int i = 0; i < nPoints; i++ )
          {
              poLine->setPoint( i, 
                                asPoints[i].x,
                                asPoints[i].y,
                                asPoints[i].z );
          }

          poFeature->SetGeometryDirectly( poLine );
          poFeature->SetStyleString( szPen );
      }
      break;

      case DGNST_TEXT:
      {
          OGRPoint      *poPoint = new OGRPoint();
          DGNElemText   *psText = (DGNElemText *) psElement;
          char          *pszOgrFS;

          poPoint->setX( psText->origin.x );
          poPoint->setY( psText->origin.y );
          poPoint->setZ( psText->origin.z );

          poFeature->SetGeometryDirectly( poPoint );

          pszOgrFS = (char *) CPLMalloc(strlen(psText->string) + 150);

          // setup the basic label.
          sprintf( pszOgrFS, "LABEL(t:\"%s\"",  psText->string );

          // set the color if we have it. 
          if( strlen(szFSColor) > 0 )
              sprintf( pszOgrFS+strlen(pszOgrFS), ",%s", szFSColor );

          // Add the size info in ground units.
          if( ABS(psText->height_mult) >= 6.0 )
              sprintf( pszOgrFS+strlen(pszOgrFS), ",s:%dg", 
                       (int) psText->height_mult );
          else if( ABS(psText->height_mult) > 0.1 )
              sprintf( pszOgrFS+strlen(pszOgrFS), ",s:%.3fg", 
                       psText->height_mult );
          else
              sprintf( pszOgrFS+strlen(pszOgrFS), ",s:%.12fg", 
                       psText->height_mult );

          // Add the font name. Name it MstnFont<FONTNUMBER> if not available
          // in the font list. #3392
          static const char *papszFontList[] =
          { "STANDARD", "WORKING", "FANCY", "ENGINEERING", "NEWZERO", "STENCEL", //0-5
            "USTN_FANCY", "COMPRESSED", "STENCEQ", NULL, "hand", "ARCH", //6-11
            "ARCHB", NULL, NULL, "IGES1001", "IGES1002", "IGES1003", //12-17
            "CENTB", "MICROS", NULL, NULL, "ISOFRACTIONS", "ITALICS", //18-23
            "ISO30", NULL, "GREEK", "ISOREC", "Isoeq", NULL, //24-29
            "ISO_FONTLEFT", "ISO_FONTRIGHT", "INTL_ENGINEERING", "INTL_WORKING", "ISOITEQ", NULL, //30-35
            "USTN FONT 26", NULL, NULL, NULL, NULL, "ARCHITECTURAL", //36-41
            "BLOCK_OUTLINE", "LOW_RES_FILLED", NULL, NULL, NULL, NULL, //42-47
            NULL, NULL, "UPPERCASE", NULL, NULL, NULL, //48-53
            NULL, NULL, NULL, NULL, NULL, NULL, //54-49
            "FONT060", "din", "dinit", "helvl", "HELVLIT", "helv", //60-65
            "HELVIT", "cent", "CENTIT", "SCRIPT", NULL, NULL, //66-71
            NULL, NULL, NULL, NULL, "MICROQ", "dotfont", //72-77
            "DOTIT", NULL, NULL, NULL, NULL, NULL, //78-83
            NULL, NULL, NULL, NULL, NULL, NULL, //84-89
            NULL, NULL, "FONT092", NULL, "FONT094", NULL, //90-95
            NULL, NULL, NULL, NULL, "ANSI_SYMBOLS", "FEATURE_CONTROL_SYSMBOLS", //96-101
            "SYMB_FAST", NULL, NULL, "INTL_ISO", "INTL_ISO_EQUAL", "INTL_ISO_ITALIC", //102-107
            "INTL_ISO_ITALIC_EQUAL" }; //108

          if(psText->font_id <= 108 && papszFontList[psText->font_id] != NULL )
          {
              sprintf( pszOgrFS+strlen(pszOgrFS), ",f:%s",
                       papszFontList[psText->font_id] );
          }
          else
          {
              sprintf( pszOgrFS+strlen(pszOgrFS), ",f:MstnFont%d",
                       psText->font_id );
          }

          // Add the angle, if not horizontal
          if( psText->rotation != 0.0 )
              sprintf( pszOgrFS+strlen(pszOgrFS), ",a:%d", 
                       (int) (psText->rotation+0.5) );

          strcat( pszOgrFS, ")" );

          poFeature->SetStyleString( pszOgrFS );
          CPLFree( pszOgrFS );

          poFeature->SetField( "Text", psText->string );
      }
      break;

      case DGNST_COMPLEX_HEADER:
      {
          DGNElemComplexHeader *psHdr = (DGNElemComplexHeader *) psElement;
          int           iChild;
          OGRMultiLineString  oChildren;

          /* collect subsequent child geometries. */
          // we should disable the spatial filter ... add later.
          for( iChild = 0; iChild < psHdr->numelems; iChild++ )
          {
              OGRFeature *poChildFeature = NULL;
              DGNElemCore *psChildElement;

              psChildElement = DGNReadElement( hDGN );
              // should verify complex bit set, not another header.

              if( psChildElement != NULL )
              {
                  poChildFeature = ElementToFeature( psChildElement );
                  DGNFreeElement( hDGN, psChildElement );
              }

              if( poChildFeature != NULL
                  && poChildFeature->GetGeometryRef() != NULL )
              {
                  OGRGeometry *poGeom;

                  poGeom = poChildFeature->GetGeometryRef();
                  if( wkbFlatten(poGeom->getGeometryType()) == wkbLineString )
                      oChildren.addGeometry( poGeom );
              }

              if( poChildFeature != NULL )
                  delete poChildFeature;
          }

          // Try to assemble into polygon geometry.
          OGRGeometry *poGeom;

          if( psElement->type == DGNT_COMPLEX_SHAPE_HEADER )
              poGeom = (OGRPolygon *) 
                  OGRBuildPolygonFromEdges( (OGRGeometryH) &oChildren, 
                                            TRUE, TRUE, 100000, NULL );
          else
              poGeom = oChildren.clone();

          if( poGeom != NULL )
              poFeature->SetGeometryDirectly( poGeom );

          ConsiderBrush( psElement, szPen, poFeature );
      }
      break;

      default:
        break;
    }
    
/* -------------------------------------------------------------------- */
/*      Fixup geometry dimension.                                       */
/* -------------------------------------------------------------------- */
    if( poFeature->GetGeometryRef() != NULL )
        poFeature->GetGeometryRef()->setCoordinateDimension( 
            DGNGetDimension( hDGN ) );

    return poFeature;
}
Example #7
0
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;
}