Part Line: Infinit/Finite 2d vs 3d

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!
User avatar
yorik
Founder
Posts: 13664
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: Part Line: Infinit/Finite 2d vs 3d

Post by yorik »

Thanks Werner!
@mlampert go into Tools->Edit Parameters and in Preferences/Mod/Part/General, add a new boolean key named "LineOld" and set it to false. Then you'll have the new behaviour, and no more warning. Then it'll be easier to debug.
As for DraftGeomUtils.geomType, I'll fix that right now...
mlampert
Veteran
Posts: 1772
Joined: Fri Sep 16, 2016 9:28 pm

Re: Part Line: Infinit/Finite 2d vs 3d

Post by mlampert »

Thanks yorik, I would have fixed it but wasn't sure what the proper fix is (without breaking something that's not covered by the self test).
wmayer
Founder
Posts: 20309
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Part Line: Infinit/Finite 2d vs 3d

Post by wmayer »

mlampert wrote:Thanks yorik, I would have fixed it but wasn't sure what the proper fix is (without breaking something that's not covered by the self test).
I guess there is somewhere a bug in the Part module which makes the Draft issues unfixable.

When I run this code snippet with the old behaviour I get the expected results:

Code: Select all

edge=Part.makeLine((1,2,3),(4,5,6))
isinstance(edge.Curve,(Part.LineSegment,Part.Line)) # True
isinstance(edge.Curve,Part.Line) # False
isinstance(edge.Curve,Part.LineSegment) # True
When I run it with the new behaviour I get:

Code: Select all

edge=Part.makeLine((1,2,3),(4,5,6))
isinstance(edge.Curve,(Part.LineSegment,Part.Line)) # False but True is expected
isinstance(edge.Curve,Part.Line) # False but True is expected
isinstance(edge.Curve,Part.LineSegment) # False
EDIT: Solved. It was my mistake.
wmayer
Founder
Posts: 20309
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Part Line: Infinit/Finite 2d vs 3d

Post by wmayer »

What would be really great is if the deprecation warning would include where it comes from, but I guess it's rather tricky to investigate/print the stack trace.
One way would be to modify TopoShapeEdgePy::getCurve() and after setting the exception add this line:

Code: Select all

throw Py::Exception();
Then the Python interpreter itself will print the stack trace.
wmayer
Founder
Posts: 20309
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Part Line: Infinit/Finite 2d vs 3d

Post by wmayer »

Yorik here is a patch which fixes the issues with the unit tests:

Code: Select all

diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py
index a6ad690..89a3b70 100644
--- a/src/Mod/Draft/Draft.py
+++ b/src/Mod/Draft/Draft.py
@@ -3140,7 +3140,7 @@ def upgrade(objects,delete=False,force=None):
             else:
                 # turn to Draft line
                 e = objects[0].Shape.Edges[0]
-                if isinstance(e.Curve,Part.LineSegment):
+                if isinstance(e.Curve,(Part.LineSegment,Part.Line)):
                     result = turnToLine(objects[0])
                     if result: msg(translate("draft", "Found 1 linear object: converting to line\n"))
 
diff --git a/src/Mod/Draft/DraftGeomUtils.py b/src/Mod/Draft/DraftGeomUtils.py
index f5cb2f7..02d900f 100755
--- a/src/Mod/Draft/DraftGeomUtils.py
+++ b/src/Mod/Draft/DraftGeomUtils.py
@@ -105,7 +105,7 @@ def isPtOnEdge(pt,edge) :
 def hasCurves(shape):
     "hasCurve(shape): checks if the given shape has curves"
     for e in shape.Edges:
-            if not isinstance(e.Curve,Part.LineSegment):
+            if not isinstance(e.Curve,(Part.LineSegment,Part.Line)):
                     return True
     return False
 
@@ -159,9 +159,9 @@ def getQuad(face):
 
 def areColinear(e1,e2):
     """areColinear(e1,e2): returns True if both edges are colinear"""
-    if not isinstance(e1.Curve,Part.LineSegment):
+    if not isinstance(e1.Curve,(Part.LineSegment,Part.Line)):
         return False
-    if not isinstance(e2.Curve,Part.LineSegment):
+    if not isinstance(e2.Curve,(Part.LineSegment,Part.Line)):
         return False
     v1 = vec(e1)
     v2 = vec(e2)
@@ -188,7 +188,7 @@ def hasOnlyWires(shape):
 def geomType(edge):
     "returns the type of geom this edge is based on"
     try:
-        if isinstance(edge.Curve,Part.LineSegment):
+        if isinstance(edge.Curve,(Part.LineSegment,Part.Line)):
             return "Line"
         elif isinstance(edge.Curve,Part.Circle):
             return "Circle"
mlampert
Veteran
Posts: 1772
Joined: Fri Sep 16, 2016 9:28 pm

Re: Part Line: Infinit/Finite 2d vs 3d

Post by mlampert »

wmayer wrote:
What would be really great is if the deprecation warning would include where it comes from, but I guess it's rather tricky to investigate/print the stack trace.
One way would be to modify TopoShapeEdgePy::getCurve() and after setting the exception add this line:

Code: Select all

throw Py::Exception();
Then the Python interpreter itself will print the stack trace.
Unfortunately I can throw whatever I want but something catches the exception and suppresses the stack trace.
mlampert
Veteran
Posts: 1772
Joined: Fri Sep 16, 2016 9:28 pm

Re: Part Line: Infinit/Finite 2d vs 3d

Post by mlampert »

I'm sure I'm doing something wrong and I'm stuck at the moment. I switched to the new LineSegment behaviour, create a Part.Box and then run:

Code: Select all

>>> from  DraftGeomUtils import geomType
>>> [geomType(e) for e in App.ActiveDocument.Box.Shape.Edges]
[<type 'Part.GeomLine'>, <type 'Part.GeomLine'>, <type 'Part.GeomLine'>, <type 'Part.GeomLine'>, <type 'Part.GeomLine'>, <type 'Part.GeomLine'>, <type 'Part.GeomLine'>, <type 'Part.GeomLine'>, <type 'Part.GeomLine'>, <type 'Part.GeomLine'>, <type 'Part.GeomLine'>, <type 'Part.GeomLine'>]
>>> Part.Line
<type 'Part.GeomLine'>
>>> 
The reason you see all these <type 'Part.GeomLine'> as output of the for comprehension is because I replaced the 'else' case in DraftGeomUtils.geomType(edge) with "return type(edge.Curve)".

It seems that somehow Part.Line is a Part.GeomLine, but when run through DraftGeomUtils.geomType() it isn't.

If anybody could point me to the flaw in my logic I would very much appreciate it and move the Path WB further along switching to the new Line/LineSegment semantics.
User avatar
yorik
Founder
Posts: 13664
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: Part Line: Infinit/Finite 2d vs 3d

Post by yorik »

this works for me, though:

Code: Select all

>>> b = Part.makeBox(1,1,1)
>>> b.Edges[0].Curve
<Line object>
>>> isinstance(b.Edges[0].Curve,Part.Line)
True
mlampert
Veteran
Posts: 1772
Joined: Fri Sep 16, 2016 9:28 pm

Re: Part Line: Infinit/Finite 2d vs 3d

Post by mlampert »

Hey yorik, thanks for your confirmation - as it turned out I only changed the default value in one of the sources, and if you change the preferences you have to restart FC. It always takes me a while to follow instructions - but once you do it works :mrgreen:
wmayer
Founder
Posts: 20309
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Part Line: Infinit/Finite 2d vs 3d

Post by wmayer »

If anybody could point me to the flaw in my logic I would very much appreciate it and move the Path WB further along switching to the new Line/LineSegment semantics.
Part.GeomLine is just the string representation of the type Part.Line. Anyway, since this might be confusing I extended our generation framework to allow to explicitly set the Python type name in the xml files.
Post Reply