View Issue Details

IDProjectCategoryView StatusLast Update
0032890CommunityOCCT:Modeling Algorithmspublic2022-03-28 21:21
Reporterdavidboyd96_163659 Assigned Tomsv 
Status newResolutionopen 
PlatformWindowsOSVC++ 2019 
Product Version7.5.0 
Summary0032890: Incorrect Geometry created by BRepOffsetAPI_MakeOffset
DescriptionHi, I've found an issue with the MakeOffset API for creating offsets of 2d wires. The issue arises when using the join type GeomAbs_Arc using a combination of line segments and circular arcs.
In some cases the algorithm incorrectly handles the intersection of arcs in the input wire with arcs added by the offset algorithm. I have a limited understanding of how offsets are calculated in OC and how the underlying BRepMAT2d classes work. I've done some limited debugging myself but delving deeply into the inner workings of the MAT2d classes is difficult with limited documentation and the French comments in the code (as a non French speaker).

Small perturbations of the vertex v6 in the attach draw code can completely remove the issue, or create multiple incorrect geometries.
The issue seems to be that arc in the input wire (with large radius relative to the rest of the edges) is intersecting with other smaller arcs in the offset.

I have a fix which makes a slight change to the BRepFill_OffsetWire::MakeOffset function but I'm not entirely sure this fixes the underlying issue, and there is a chance the code I'm fixing has other purposes which I'm not aware of. My fix makes changes within the "if (AC.GetType() == GeomAbs_Circle)" branch, specifically:

Standard_Real Delta = 2 * M_PI - l + f;
if (theJoinType == GeomAbs_Arc)
    if (ToExtendFirstPar)
        f -= 0.2 * Delta;
    if (ToExtendLastPar)
        l += 0.2 * Delta;

I might be making incorrect assumptions in the following, but I assume that the purpose of the Delta variable is to give the difference between the first and last parameter. In this case the first parameter is Pi/4 and the last parameter is Pi/2, the difference of course being Pi/4. The above code sets Delta to 7Pi/4 which is considerably larger than the range of the arc. The problem is that this Delta is seemingly arbitrarily multiplied by 0.2. I don't see where 0.2 has come from but it makes the range of the arc to be considered for intersection much larger than the actual arc. I also don't see the case were ToExtendFirstPar and ToExtendLastPar are relevant when using GeomAbs_Arc. Surely the parameter range doesn't need to change when using GeomAbs_Arc, because adjacent edges are by definition guaranteed to intersect the new arcs? Changing the above code to:

Standard_Real Delta = 2 * M_PI - l + f;
if (theJoinType == GeomAbs_Arc)
    if (ToExtendFirstPar)
        f -= 0;
    if (ToExtendLastPar)
        l += 0;

or something similar (like removing the whole if statement), fixes the issue in the limited example which I've given. Of course, there may be cases where changing "f" and "l" is necessary but I can't see what these cases are when using GeomAbs_Arc. This also might just be more of a hot fix. The real issue may be further within the MAT2d classes but as I mentioned previously, I am not aware of the overall structure of how these classes work. One thing I wanted to ask was what MAT is an acronym for? I've looked through the doxygen documentation and parts of the code but I haven't been able to find anything which explains what this actually means. At one point I thought it might be related to the medial axis transform but that seems unlikely for an offset algorithm.

I've attached photos of the different error cases with different values of the vertex v6.

Having said all of the above, I've done some testing by changing the last few lines of my draw code to:

mkoffset off p1 7 2 a

don p1 off_*

and the cases with different v6 result in errors after the offset reaches a certain threshold so my above fix clearly doesn't fix the issue and there is something else going on with the offset algorithm. Further debugging is clearly needed to solve the issue.
Steps To Reproducecircle circ 0 37 0 0 0 1 20
reverse circ
mkedge edge_circ circ pi/4 pi/2
vertex circStart pi/4 edge_circ
vertex circEnd pi/2 edge_circ
mkpoint circStartPnt circStart
mkpoint circEndPnt circEnd
coord circStartPnt circStartX circStartY circStartZ
coord circEndPnt circEndX circEndY circEndZ

vertex v1 0 0 0
vertex v2 30 30 0
vertex v3 circStartX+2 30 0
vertex v4 circStartX+2 circStartY+2 0
vertex v5 circEndX-2 circEndY 0

vertex v6 circEndX-5 circEndY+1 0; # incorrect geometry
#vertex v6 circEndX-5 circEndY+4 0;# correct
#vertex v6 circEndX-5 circEndY+7 0;# different incorrect geometry

edge e1 v1 v2
edge e2 v2 v3
edge e3 v3 v4
edge e4 v4 circStart
edge e5 circEnd v5
edge e6 v5 v6
edge e7 v6 v1
wire w1 e1 e2 e3 e4 edge_circ e5 e6 e7
mkplane p1 w1

mkoffset off p1 1 2 a

donly p1 off_1
TagsNo tags attached.
Test case number

Attached Files

  • vertex_v6_plus1.png (14,152 bytes)
  • vertex_v6_plus4.png (16,266 bytes)
  • vertex_v6_plus7.png (14,995 bytes)



2022-03-25 21:03


vertex_v6_plus1.png (14,152 bytes)
vertex_v6_plus4.png (16,266 bytes)
vertex_v6_plus7.png (14,995 bytes)


2022-03-26 21:05

developer   ~0107433

You can read the article that presents the mathematical theory of the two-dimensional offset curves from the viewpoint of medial axis transform:


2022-03-28 21:21

reporter   ~0107451

@msv Thanks for confirming this. I actually came across that paper last week but wasn't sure if this was the approach used in OCCT. Seeing that the medial axis transform is used in this case, I guess the issue is more complicated than my "fix" suggests.

Issue History

Date Modified Username Field Change
2022-03-25 21:03 davidboyd96_163659 New Issue
2022-03-25 21:03 davidboyd96_163659 Assigned To => msv
2022-03-25 21:03 davidboyd96_163659 File Added: vertex_v6_plus1.png
2022-03-25 21:03 davidboyd96_163659 File Added: vertex_v6_plus4.png
2022-03-25 21:03 davidboyd96_163659 File Added: vertex_v6_plus7.png
2022-03-26 21:05 msv Note Added: 0107433
2022-03-28 21:21 davidboyd96_163659 Note Added: 0107451