BUG in Draft.makeCircle()

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
dino
Posts: 113
Joined: Mon Sep 22, 2014 11:28 pm

BUG in Draft.makeCircle()

Post by dino »

Hi,
I think there is a BUG in Draft.makeCircle() from Part.ArcOfCircle()

The arc created by Draft.makeCircle() NOT coincide with the arc created by Part.ArcOfCircle() (the arc created by Part.ArcOfCircle() it is right, it touch the points, the other by Draft.makeCircle() do not touch!)
MakeArcFromPartOfCircle.FCMacro
(384 Bytes) Downloaded 33 times
Need open a BUG report?

Thanks
Dino

OS: Devuan GNU/Linux beowulf/ceres
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.18.
Build type: Release
Python version: 2.7.16rc1
Qt version: 5.11.3
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: Italian/Italy (it_IT)
Attachments
ArcFromArc.png
ArcFromArc.png (42.23 KiB) Viewed 1265 times
User avatar
Joel_graff
Veteran
Posts: 1949
Joined: Fri Apr 28, 2017 4:23 pm
Contact:

Re: BUG in Draft.makeCircle()

Post by Joel_graff »

dino wrote: Wed Mar 13, 2019 11:38 pm I think there is a BUG in Draft.makeCircle() from Part.ArcOfCircle()
This is not a bug. It's simply curve tessellation. The tessellations don't align because the beginning and ending points of your arcs are not aligned.

The arcs are mathematically precise and if you discretize them (using Shape.discretize()), they will provide coordinates along the perimeter of the arc without error. The visual representation is, of course, less accurate because it is subdivided into straight-line segments (or tessellated).

You can control the visual accuracy by editing the Part Design Preferences as follows:

  • Open Edit->Preferences
  • Click on the 'Part Design' icon on the left.
  • Select the 'Shape View' tab at the top on the right.
At the top of the Shape View page, in the 'Tessellation' property group, you will see a property entitled 'Maximum deviation depending on model bounding box' with a corresponding percentage value.

You can reduce that percentage to as low as 0.01%. If you rebuild your objects, you'll very likely find they look much smoother. Of course, if you zoom in far enough, you'll see the tessellation clearly.

Note that the percentage is based on the size of the model bounding box - it's not a fixed length. So a much larger object will have much larger tessellations at the same percentage. In order to avoid that, you need to plot the arc manually as a wire, calculating the points using the equation of a circle. Or you can discretize the existing arc to get a list of closely-spaced points and build a Wire from those.
FreeCAD Trails workbench for transportation engineering: https://www.github.com/joelgraff/freecad.trails

pivy_trackers 2D coin3D library: https://www.github.com/joelgraff/pivy_trackers
dino
Posts: 113
Joined: Mon Sep 22, 2014 11:28 pm

Re: BUG in Draft.makeCircle()

Post by dino »

No, this not is a curve tessellation, if you run the script will see that the error is real, measure distance from the end of the Shape and Circle and see that it is a BIG error (4.81434mm)
dino
Posts: 113
Joined: Mon Sep 22, 2014 11:28 pm

Re: BUG in Draft.makeCircle()

Post by dino »

Dear,
the error is in Mod/Draft/Draft.py at line 709, the reference vector is horizontal East direction not "placement.multVec(FreeCAD.Vector(1,0,0))".
Need to correct it!
To whom should the reported the BUG?

Have a nice day
Dino
User avatar
Joel_graff
Veteran
Posts: 1949
Joined: Fri Apr 28, 2017 4:23 pm
Contact:

Re: BUG in Draft.makeCircle()

Post by Joel_graff »

dino wrote: Thu Mar 14, 2019 2:28 pm Dear,
the error is in Mod/Draft/Draft.py at line 709, the reference vector is horizontal East direction not "placement.multVec(FreeCAD.Vector(1,0,0))".
Need to correct it!
To whom should the reported the BUG?
My mistake - I see what you're referring to, now.

Obviously, Part.ArcOfCircle builds the arc from pre-defined vertices, whereas Draft.makeCircle essentially needs a start angle, end angle, and radius to create the arc. In FreeCAD, arc angles are measured from the positive x-axis (east - Vector(1,0,0)) not the positive y-axis (north - Vector(0,1,0)).

While it's certainly inconvenient for those of us who prefer angles measured from true north (myself included), this is not a bug. You'll simply need to account for this difference in convention in the calculation of your Part.ArcOfCircle vertices.
FreeCAD Trails workbench for transportation engineering: https://www.github.com/joelgraff/freecad.trails

pivy_trackers 2D coin3D library: https://www.github.com/joelgraff/pivy_trackers
dino
Posts: 113
Joined: Mon Sep 22, 2014 11:28 pm

Re: BUG in Draft.makeCircle()

Post by dino »

The method to convert an arc from the form of Part.ArcOfCircle to the Draft form was not implemented by me, I simply used Draft.makeCircle(edge) which contains a BUG, an incorrect vector is taken as a reference to calculate the start and end angles of the arc.

Code: Select all

def makeCircle(radius, placement=None, face=None, startangle=None, endangle=None, support=None):
... cut ...
if isinstance(radius,Part.Edge):
        edge = radius
        if DraftGeomUtils.geomType(edge) == "Circle":
            obj.Radius = edge.Curve.Radius
            placement = FreeCAD.Placement(edge.Placement)
            delta = edge.Curve.Center.sub(placement.Base)
            placement.move(delta)
            if len(edge.Vertexes) > 1:
                ref = placement.multVec(FreeCAD.Vector(1,0,0))
                v1 = (edge.Vertexes[0].Point).sub(edge.Curve.Center)
                v2 = (edge.Vertexes[-1].Point).sub(edge.Curve.Center)
                a1 = -math.degrees(DraftVecUtils.angle(v1,ref))
                a2 = -math.degrees(DraftVecUtils.angle(v2,ref))
                obj.FirstAngle = a1
                obj.LastAngle = a2
    else:
... cut ...
the correct ref vector is

Code: Select all

                ref = FreeCAD.Vector(1,0,0)
User avatar
Joel_graff
Veteran
Posts: 1949
Joined: Fri Apr 28, 2017 4:23 pm
Contact:

Re: BUG in Draft.makeCircle()

Post by Joel_graff »

dino wrote: Sat Mar 16, 2019 6:18 pm an incorrect vector is taken as a reference to calculate the start and end angles of the arc.
I think I finally see your point. :) It dawned on me that you're defining the arc using an existing shape (instead of points - which works perfectly). I agree, it does look wrong.

Pinging Yorik on this.
yorik wrote: ping
FreeCAD Trails workbench for transportation engineering: https://www.github.com/joelgraff/freecad.trails

pivy_trackers 2D coin3D library: https://www.github.com/joelgraff/pivy_trackers
dino
Posts: 113
Joined: Mon Sep 22, 2014 11:28 pm

Re: BUG in Draft.makeCircle()

Post by dino »

I have checked my solution proposed here and works correctly only if the arc is on XY plane, if rot the arc in the space before converting it fail again, because need to check the plane on the arc is rapresented. In next days I try to correct it.

:D :D
User avatar
Joel_graff
Veteran
Posts: 1949
Joined: Fri Apr 28, 2017 4:23 pm
Contact:

Re: BUG in Draft.makeCircle()

Post by Joel_graff »

dino wrote: Mon Mar 18, 2019 9:57 pm I have checked my solution proposed here and works correctly only if the arc is on XY plane, if rot the arc in the space before converting it fail again, because need to check the plane on the arc is rapresented. In next days I try to correct it.
You can submit a pull request for the fix if you like, if you know your way around git... Otherwise, give @yorik (or @wmayer) time to look at it and address it. We're in the middle of a release, so they may not get to it right away.
FreeCAD Trails workbench for transportation engineering: https://www.github.com/joelgraff/freecad.trails

pivy_trackers 2D coin3D library: https://www.github.com/joelgraff/pivy_trackers
dino
Posts: 113
Joined: Mon Sep 22, 2014 11:28 pm

Re: BUG in Draft.makeCircle()

Post by dino »

Ok,
I have corrected the BUG (I think :))
The correct code is:

Code: Select all

cut...

    if isinstance(radius,Part.Edge):
        edge = radius
        if DraftGeomUtils.geomType(edge) == "Circle":
            obj.Radius = edge.Curve.Radius
            placement = FreeCAD.Placement(edge.Placement)
            delta = edge.Curve.Center.sub(placement.Base)
            placement.move(delta)
            # Rotation of the edge 
            rotOk = FreeCAD.Rotation(edge.Curve.XAxis, edge.Curve.YAxis, edge.Curve.Axis, "ZXY")
            placement.Rotation = rotOk
            if len(edge.Vertexes) > 1:
                #ref = placement.multVec(FreeCAD.Vector(1,0,0))
                #ref = ref.sub(edge.Curve.Center)
                v1 = (edge.Vertexes[0].Point).sub(edge.Curve.Center)
                v2 = (edge.Vertexes[-1].Point).sub(edge.Curve.Center)
                #a1 = -math.degrees(DraftVecUtils.angle(v1,ref))
                #a2 = -math.degrees(DraftVecUtils.angle(v2,ref))
                v0 = (edge.Curve.XAxis).normalize() 
                v1.normalize()
                v2.normalize()
                # Angle between edge.Curve.XAxis and the vector from center to start of arc 
                obj.FirstAngle = math.degrees(math.acos((v0.x*v1.x)+(v0.y*v1.y)+(v0.z*v1.z)))
                # Angle between edge.Curve.XAxis and the vector from center to end of arc 
                obj.LastAngle = math.degrees(math.acos((v0.x*v2.x)+(v0.y*v2.y)+(v0.z*v2.z)))
                
cut...
Please can check it?

D
Post Reply