OSGeo / gdal

GDAL is an open source MIT licensed translator library for raster and vector geospatial data formats.
https://gdal.org
Other
4.82k stars 2.52k forks source link

DXF polyline circle like shape wrongly recognized as tiny arc segment #1839

Open igorthy opened 5 years ago

igorthy commented 5 years ago

Hi,

I have a DFX file which I reduced to single block containing single polyline shape. In Autocad 2019 it looks like: bug If you read it into memory/write shapefile with DXF driver it translates polyline to single line segment. It is true for gdal 3.0.0 and for 3.0.1 releases. DXF file attached (after download change extension to dxf):

polyline.txt

Any help highly appreciated.

rouault commented 5 years ago

CC @atlight

igorthy commented 5 years ago

I got a chance to debug this problem during last weekend and find the place where it goes wrong but I didn't have yet the time to work on solution. The shape inside DXF file is polyline defined by two points (very close to each other) and a bulge factor. In ogrdxf_polyline_smooth.cpp file there is a method DXFSmoothPolyline::EmitArc that calculates arc parameters for subsequent OGRGeometryFactory::approximateArcAngles call. This calculation need to be reviewed. First it seems that there is some issue with clockwise/anticlockwise choice of algorithm. When I reversed the sign of bulge value in DXF file the method generated the correct linestring BUT at wrong location.

It would be very nice if someone could fix this quickly. I will try to fix it myself when I'll have an opportunity. Thanks

igorthy commented 5 years ago

I believe I have a fix for this issue. I debugged through calculation done in DXFSmoothPolyline::EmitArc (see ogrdxf_polyline_smooth.cpp file). I found out that clockwise arc calculated correctly but exactly same anticlockwise arc calculated wrong as tiny arc. It seemed like it has to do something with starting and ending angles. See these lines:

    if(!bClockwise && (ogrArcStartAngle < ogrArcEndAngle))
        ogrArcEndAngle = -180.0 + (linedir * a);

    if(bClockwise && (ogrArcStartAngle > ogrArcEndAngle))
        ogrArcEndAngle += 360.0;

These lines make sure that ogrArcStartAngle and ogrArcEndAngle angles agree with clockwise/anticlockwise arc direction. I expected it to be symmetrical with respect to variable substitution. So in first two-liner I replaced ogrArcEndAngle = -180.0 + (linedir * a); with ogrArcStartAngle += 360.0; or ogrArcEndAngle -= 360.0;

This resolves the issue I described in this thread. I don't mean to underestimate the existing line but it seems wrong to me. I guess it might work for certain private cases.

Following the same "symmetry" argument I don't quite understand why there is a concern about the case:

    if(bClockwise && (linedir == 1.0))
        a += (linedir * 180.0);

but not about something like:

    if(!bClockwise && (linedir == -1.0))
        a += (linedir * 180.0);