Sketch Inside/Outside Curve

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
paullee
Veteran
Posts: 5097
Joined: Wed May 04, 2016 3:58 pm

Re: Sketch Inside/Outside Curve

Post by paullee »

paullee wrote: Fri Dec 03, 2021 7:15 pm Test if the wire one by one if it is closed; then test the wires if they are 'inside' or 'outside' against the outerwire ( pick a point along the wire and test by algorithm discussed above?). Then test the concerned curve with @Roy_043's approach - but the reverse of the logic is true?
This may be useful ?

Code: Select all

Face.isInside(point)
keithsloan52
Veteran
Posts: 2756
Joined: Mon Feb 27, 2012 5:31 pm

Re: Sketch Inside/Outside Curve

Post by keithsloan52 »

Roy_043 wrote: Fri Dec 03, 2021 2:39 pm For the outer wire this can work:
Create a face from the sketch: face = Part.makeFace(sketch.Shape, "Part::FaceMakerSimple").
Get an ordered_vertexes_list: face.OuterWire.OrderedVertexes.
For each arc check the order of edge.firstVertex() and edge.lastVertex() in ordered_vertexes_list.
If the order is first->last the arc is convex.

To check if a point is inside the face you can use its isInside() method.
I tried coding

Code: Select all

    sketchFace = Part.makeFace(sketchObj.Shape, "Part::FaceMakerSimple")
    print(dir(sketchFace))
    vertList = sketchFace.OuterWire.OrderedVertexes
But not seeing an OuterWire, the print(dir( outputs

Code: Select all

09:22:01  ['Area', 'BoundBox', 'CompSolids', 'Compounds', 'Content', 'Edges', 'Faces', 'Length', 'Matrix', 'MemSize', 'Module', 'Orientation', 'Placement', 'ShapeType', 'Shells', 'Solids', 'SubShapes', 'Tag', 'TypeId', 'Vertexes', 'Volume', 'Wires', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', 'add', 'ancestorsOfType', 'check', 'childShapes', 'cleaned', 'common', 'complement', 'connectEdgesToWires', 'copy', 'countElement', 'cut', 'defeaturing', 'distToShape', 'dumpContent', 'dumpToString', 'exportBinary', 'exportBrep', 'exportBrepToString', 'exportIges', 'exportStep', 'exportStl', 'extrude', 'findPlane', 'fix', 'fixTolerance', 'fuse', 'generalFuse', 'getAllDerivedFrom', 'getElement', 'getFacesFromSubelement', 'getTolerance', 'globalTolerance', 'hashCode', 'importBinary', 'importBrep', 'importBrepFromString', 'inTolerance', 'isClosed', 'isCoplanar', 'isDerivedFrom', 'isEqual', 'isInfinite', 'isInside', 'isNull', 'isPartner', 'isSame', 'isValid', 'limitTolerance', 'makeChamfer', 'makeFillet', 'makeOffset2D', 'makeOffsetShape', 'makeParallelProjection', 'makePerspectiveProjection', 'makeShapeFromMesh', 'makeThickness', 'makeWires', 'mirror', 'multiFuse', 'nullify', 'oldFuse', 'optimalBoundingBox', 'overTolerance', 'project', 'proximity', 'read', 'reflectLines', 'removeInternalWires', 'removeShape', 'removeSplitter', 'replaceShape', 'restoreContent', 'reverse', 'reversed', 'revolve', 'rotate', 'rotated', 'scale', 'scaled', 'section', 'sewShape', 'slice', 'slices', 'tessellate', 'toNurbs', 'transformGeometry', 'transformShape', 'transformed', 'translate', 'translated', 'writeInventor']
09:22:01  Traceback (most recent call last):
keithsloan52
Veteran
Posts: 2756
Joined: Mon Feb 27, 2012 5:31 pm

Re: Sketch Inside/Outside Curve

Post by keithsloan52 »

I tried the following

Code: Select all

sketchFace = Part.makeFace(sketchObj.Shape, "Part::FaceMakerSimple")

and when looping through geometry
if case('Part::GeomArcOfCircle') :
              print('ArcofCircle')
              print(dir(gs))
              # Is Inside(point, tolerance, if onSurface)
              print(sketchFace.isInside(gs.Center,0.001,False))
And all my Arc's are returning False :-(

If I change to

Code: Select all

print(sketchObj.Shape.isInside(gs.Center,0.001,False))
They all return True :-(

Does isInside actually check the face/shape or just the bounding box?

Don't know if the following info helps
sketchFace.isClosed() on the Face returns False where as sketchObj.Shape.isClosed() returns True.
Sketch is fully constrained as per original post see attached file
TestExtrudeSketch.FCStd
(132.4 KiB) Downloaded 16 times
keithsloan52
Veteran
Posts: 2756
Joined: Mon Feb 27, 2012 5:31 pm

SOLVED: Re: Sketch Inside/Outside Curve

Post by keithsloan52 »

Think there maybe a bug with isInside

If I code

Code: Select all

print(sketchFace.isInside(gs.Center,0.001,True))
I get the correct results but not when i had

Code: Select all

print(sketchFace.isInside(gs.Center,0.001,False))
I did not.

Now my understanding of the third parameter was what to return if the point is on the surface
so in my case it should have been the same whether set to True or False.
keithsloan52
Veteran
Posts: 2756
Joined: Mon Feb 27, 2012 5:31 pm

Re: Sketch Inside/Outside Curve

Post by keithsloan52 »

Now I am left with the inner circle to deal with.
Checking isInside is returning True and the action I need to take is the same as arc of a circle on the outer edge where isInside returns False.
I need some way of determining if it is an inner part of the sketch ideally when I am scanning the geometry
User avatar
Roy_043
Veteran
Posts: 8450
Joined: Thu Dec 27, 2018 12:28 pm

Re: Sketch Inside/Outside Curve

Post by Roy_043 »

keithsloan52 wrote: Mon Dec 06, 2021 12:20 pm in my case it should have been the same whether set to True or False.
Since we are dealing with a single face, and not a solid, the third parameter should be set to True.

Because of the nested circle the Part.makeFace function requires a different facemaker class. With "Part::FaceMakerSimple" it returns a compound instead of a face here (FreeCAD curve ball :mrgreen:).

Here is the algorithm I had in mind:

Code: Select all

import FreeCAD as App
import Part

sketchObj = App.ActiveDocument.Sketch
sketchFace = Part.makeFace(sketchObj.Shape, "Part::FaceMakerBullseye")
vertList = sketchFace.OuterWire.OrderedVertexes
pointList = [vert.Point for vert in vertList]
for idx_edge, edge in enumerate(sketchObj.Shape.Edges):
    if type(edge.Curve) == Part.Circle:
        print("Edge index = " + str(idx_edge))
        first = edge.firstVertex().Point
        last = edge.lastVertex().Point
        cen = edge.Curve.Center
        if first in pointList and last in pointList:
            idx_first = pointList.index(first)
            idx_last = pointList.index(last)
            if idx_last == 0 or idx_first < idx_last:
                print("convex")
            else:
                print("concave")
            if sketchFace.isInside(cen, 1e-8, True):
                print("center inside face")
            else:
                print("center outside face")
        else:
            print("nested circle or arc")
paullee
Veteran
Posts: 5097
Joined: Wed May 04, 2016 3:58 pm

Re: Sketch Inside/Outside Curve

Post by paullee »

keithsloan52 wrote: Mon Dec 06, 2021 1:56 pm Now I am left with the inner circle to deal with.
Checking isInside is returning True and the action I need to take is the same as arc of a circle on the outer edge where isInside returns False.
I need some way of determining if it is an inner part of the sketch ideally when I am scanning the geometry
Ride on @roy_043's approach above, take any point on the inner wire, and test against the face resulted - face.isInside(point on inner wire) ?
User avatar
onekk
Veteran
Posts: 6144
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Sketch Inside/Outside Curve

Post by onekk »

keithsloan52 wrote: Mon Dec 06, 2021 9:30 am But not seeing an OuterWire, the print(dir( outputs

This could may be related to FreeCAD version.

From what I could see OuterWire is present in at least 0.20 (maybe not in 0.19), sadly I can't see more, but I remember that something was deprecated in favour of Outerwire.

It seems that not all objects have an OuterWire, but Wires is almost everytime present, I suspect that it could related to the way "Face" is build.

More investigation could be done, or maybe someone who know things better could explain something.

Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
TheMarkster
Veteran
Posts: 5505
Joined: Thu Apr 05, 2018 1:53 am

Re: Sketch Inside/Outside Curve

Post by TheMarkster »

Don't use FaceMakerSimple if you might have holes in the face. Use FaceMakerCheese, or even better, FaceMakerBullseye.

Edit: to expand a bit more -- FaceMakerSimple and FaceMakerExtrusion will fill in the holes with face. In those cases you might get bad results from isInside().

Consider this sketch.
Snip macro screenshot-f42afc.png
Snip macro screenshot-f42afc.png (81.48 KiB) Viewed 1231 times
With FaceMakerSimple:
Snip macro screenshot-265432.png
Snip macro screenshot-265432.png (79.12 KiB) Viewed 1231 times
With FaceMakerBullseye:
Snip macro screenshot-db8d5c.png
Snip macro screenshot-db8d5c.png (81.21 KiB) Viewed 1231 times
User avatar
Roy_043
Veteran
Posts: 8450
Joined: Thu Dec 27, 2018 12:28 pm

Re: Sketch Inside/Outside Curve

Post by Roy_043 »

TheMarkster wrote: Tue Dec 07, 2021 1:00 am Don't use FaceMakerSimple if you might have holes in the face.
As already mentioned: with "Part::FaceMakerSimple" Part.makeFace will return a compound not a face. I have not looked at the compound, but this behavior seems strange to me.
Post Reply