Flipped arcs in DXF export - suggested fix

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
nahshon
Posts: 225
Joined: Wed Jul 24, 2013 8:06 pm

Flipped arcs in DXF export - suggested fix

Post by nahshon »

Using a fairly recent GIT version.

Arcs are flipped if they are:
(a) Clockwise.
(b) Exactly half circle (180 degrees).

The sketcher normally uses CCW arcs so the problem is rarely seen. It will happen to all half circles if the sketch is rotated by 180 degrees around the X or Y axes.

Looks like an attempt to fix the problem (change in importDXF.py from April 18) by comparing arc lengths... This works OK except for arcs that are exactly half circle.

Here's my suggested fix. Using the Circle's Axis to determine its direction.

Code: Select all

diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py
index 467e8d9..a3de207 100644
--- a/src/Mod/Draft/importDXF.py
+++ b/src/Mod/Draft/importDXF.py
@@ -1352,10 +1352,11 @@ def getArcData(edge):
         ang1 = -math.degrees(DraftVecUtils.angle(ve1.sub(ce)))
         ang2 = -math.degrees(DraftVecUtils.angle(ve2.sub(ce)))
         
-        a1 = -DraftVecUtils.angle(ve1.sub(ce))
-        a2 = -DraftVecUtils.angle(ve2.sub(ce))
-        pseudoarc = Part.ArcOfCircle(edge.Curve,a1,a2).toShape()
-        if round(pseudoarc.Length,Draft.precision()) != round(edge.Length,Draft.precision()):
+        #a1 = -DraftVecUtils.angle(ve1.sub(ce))
+        #a2 = -DraftVecUtils.angle(ve2.sub(ce))
+        #pseudoarc = Part.ArcOfCircle(edge.Curve,a1,a2).toShape()
+        #if round(pseudoarc.Length,Draft.precision()) != round(edge.Length,Draft.precision()):
+        if edge.Curve.Axis.z < 0:
             ang1, ang2 = ang2, ang1
         
         # method 2 - check the midpoint - not reliable either
User avatar
yorik
Founder
Posts: 13659
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: Flipped arcs in DXF export - suggested fix

Post by yorik »

Hi,
Thanks a lot for your suggestion, I just tested and indeed it works very nicely for arcs drawn in the XY plane... The problem is of course when arcs are in different planes, where Axis.z can be zero...
But I agree that 99% of the arcs exported to DXF are probably in the XY plane... Maybe we could adapt your code so it is only used when the Axis has x=0 and y=0, otherwise it falls back to the previous system
User avatar
shoogen
Veteran
Posts: 2823
Joined: Thu Dec 01, 2011 5:24 pm

Re: Flipped arcs in DXF export - suggested fix

Post by shoogen »

i membered that we had a similar problem with SVG export.

Code: Select all

flag_sweep = edge.Curve.Axis*drawing_plane_normal < 0
Does the drawing_plane also apply to the DXF export?
logari81
Posts: 658
Joined: Mon Jun 14, 2010 6:00 pm

Re: Flipped arcs in DXF export - suggested fix

Post by logari81 »

I always see programmers struggling with arcs. Arcs are easy, just follow the rule below:

Instead of trying to cover any possible orientation of an arc, just rotate the arc to a well defined and easy to handle orientation. Then solve the problem you want to solve and then rotate the results back to the original orientation.

By ignoring this rule you can almost guaranteed write buggy code.

How this rule applies in this specific case:

1. Find the angles ang0, ang1 and ang2 of the arc midpoint and endpoints respectively
2. Transform the coordinate axes so that ang0 will define the x-axis:
ang1 = atan2(-sin(ang0)*cos(ang1)+cos(ang0)*sin(ang1), cos(ang0)*cos(ang1)+sin(ang0)*sin(ang1))
ang2 = atan2(-sin(ang0)*cos(ang2)+cos(ang0)*sin(ang2), cos(ang0)*cos(ang2)+sin(ang0)*sin(ang2))
here I assume that atan2(y,x) returns values within [-pi,pi]
3. If ang1*ang2>0 print an error
4. If ang1 > ang2 then swap ang1,ang2 so that you will always have counterclockwise arcs
5. Transform back to the original axes:
ang1 += ang0
ang2 += ang0
6. optionally you can wrap ang1, and ang2 to [0,2*pi] or [-pi,pi] if necessary

(please check the equations for typos)
User avatar
shoogen
Veteran
Posts: 2823
Joined: Thu Dec 01, 2011 5:24 pm

Re: Flipped arcs in DXF export - suggested fix

Post by shoogen »

logari81 wrote:Instead of trying to cover any possible orientation of an arc, just rotate the arc to a well defined and easy to handle orientation. Then solve the problem you want to solve and then rotate the results back to the original orientation.
OCC automatically converts every arc to CCW by inverting the axis. We simply need to get this information back.
nahshon
Posts: 225
Joined: Wed Jul 24, 2013 8:06 pm

Re: Flipped arcs in DXF export - suggested fix

Post by nahshon »

yorikvanhavre wrote:Hi,
Thanks a lot for your suggestion, I just tested and indeed it works very nicely for arcs drawn in the XY plane... The problem is of course when arcs are in different planes, where Axis.z can be zero...
But I agree that 99% of the arcs exported to DXF are probably in the XY plane... Maybe we could adapt your code so it is only used when the Axis has x=0 and y=0, otherwise it falls back to the previous system
Arcs in other planes must be transformed to ellipse-arcs and I did not yet see that supported at all... Any attempt with rotating the part around the x or y axes in other that 180 degrees just causes arcs to be ignored.
If the Axis.z is 0 then it is parallel to the drawing plane and the arc is deformed to a straight line!
shoogen wrote:Does the drawing_plane also apply to the DXF export?
Indeed.. is that supported in DXF export and how do I find the direction vector for it?

If drawing_plane applies to dxf output then a better thing to do:

Code: Select all

      drawing_plane_direction = {direction vector for the drawing plane}
      ...
      if drawing_plane_direction.dot(edge.Curve.Axis) < 0: 
            ang1, ang2 = ang2, ang1         
My first suggestion was under the assumption that with DXF exports the drawing_plane_direction is always Vector(0, 0, 1).
logari81
Posts: 658
Joined: Mon Jun 14, 2010 6:00 pm

Re: Flipped arcs in DXF export - suggested fix

Post by logari81 »

shoogen wrote:OCC automatically converts every arc to CCW by inverting the axis. We simply need to get this information back.
I do not say that one has to handle arcs himself, if there is already an off-the-shelf solution. But if one needs to handle arcs himself, then there is only one robust way.
User avatar
yorik
Founder
Posts: 13659
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: Flipped arcs in DXF export - suggested fix

Post by yorik »

Thanks for that code logari81, definitely precious to me...
I'll play with it and see how our dxf exporter behaves.
User avatar
shoogen
Veteran
Posts: 2823
Joined: Thu Dec 01, 2011 5:24 pm

Re: Flipped arcs in DXF export - suggested fix

Post by shoogen »

I revoke what i said ealier about the drawing plane. DXF is, unlike SVG, a 3D format. The Draft drawing plane does not apply.
yorikvanhavre wrote:Hi,
Thanks a lot for your suggestion, I just tested and indeed it works very nicely for arcs drawn in the XY plane... The problem is of course when arcs are in different planes, where Axis.z can be zero...
I think that this has to be addressed in the dxfLibrary because if the arc does not lie in XY plane this information won't be saved to the DXF file.
please consider to add support for group code 210 "Extrusion direction. (optional; default = 0, 0, 1)"

Code: Select all

zdot=edge.Curve.Axis.dot(FreeCAD.Vector(0,0,1))
#round zdot
if zdot == 1: # CCW: keep angles, omit GC 210
elif zdot == -1: #CW exchange angles, omit GC 210
else: #not in XY plane keep angles and supply axis vector with GC 210
EDIT: Support for GC 210-230 in dxfLibrary.py is present for ELLIPSE but not for CIRCLE and ARC
User avatar
yorik
Founder
Posts: 13659
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: Flipped arcs in DXF export - suggested fix

Post by yorik »

yorikvanhavre wrote:EDIT: Support for GC 210-230 in dxfLibrary.py is present for ELLIPSE but not for CIRCLE and ARC
Yeah I added the ellipse code myself some time ago... Indeed would be good to add that to arcs too.
Post Reply