REVISIT: Help with computing shared face.

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
edwilliams16
Veteran
Posts: 3108
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Help with computing shared face.

Post by edwilliams16 »

keithsloan52 wrote: Sat Jun 25, 2022 4:04 pm I
Obj is Part (GDML Volume ) that contains a GDMLBox. There are five Volumes Det and 4 linked volumes Det__001 to Det__004 that all contain
the same GDMLTube.

It is possible to have boardersurfaces between Obj and the various volumes because all the GDMLTubes lie on a plane of one side of Obj's GDMLBox, this is what I need to check for. I apologies that compute shared faces is probably not the best definition of the problem.
Can you be more explicit in geometrical terms? I don't understand you. What is a GDMLTube and where is it in the file? The dets appear to be discs - before they were cubes.
keithsloan52
Veteran
Posts: 2756
Joined: Mon Feb 27, 2012 5:31 pm

Re: Help with computing shared face.

Post by keithsloan52 »

edwilliams16 wrote: Sat Jun 25, 2022 7:21 pm
keithsloan52 wrote: Sat Jun 25, 2022 4:04 pm I
Obj is Part (GDML Volume ) that contains a GDMLBox. There are five Volumes Det and 4 linked volumes Det__001 to Det__004 that all contain
the same GDMLTube.

It is possible to have boardersurfaces between Obj and the various volumes because all the GDMLTubes lie on a plane of one side of Obj's GDMLBox, this is what I need to check for. I apologies that compute shared faces is probably not the best definition of the problem.
Can you be more explicit in geometrical terms? I don't understand you. What is a GDMLTube and where is it in the file? The dets appear to be discs - before they were cubes.
I need to be able to check if any two GDMLsolids have a shared face, meaning they have a Face that is 0 distance from a Face in a second GDMLSolid and in the same plane.

GDMLsolids are documented at https://geant4-userdoc.web.cern.ch/User ... ght=solids.

For the GDML workbench they are all implemented as Part::FeaturePython objects which have an appropriate Shape, constructed from the parameters/properties.

I am happy with my implementation of skinsurface, the facility I have a challenge with is bordersurface which required me to check if two objects have a shared face as described above.

I believe the person requesting the implementaion of skinsurface and bordersurface is a Research Fellow at Harvard Medical https://gordon.mgh.harvard.edu/gc/peopl ... i-hashemi/

see the discussion at https://github.com/KeithSloan/GDML/discussions/93

The first example with Cubes was just a example of optical objects from the Geant4 distribution, the example with Tubes was just another example, the code needs to work in general with any two GDML Solids.
keithsloan52
Veteran
Posts: 2756
Joined: Mon Feb 27, 2012 5:31 pm

Re: Help with computing shared face.

Post by keithsloan52 »

Okay back to testing with the cubes, I am trying

Code: Select all

def commonFace(self, shape0, shape1):
        zero = FreeCAD.Vector(0.0, 0.0, 0.0)
        for i, face0 in enumerate(shape0.Faces):
            for j, face1 in enumerate(shape1.Faces):
               if face0.isCoplanar(face1):
                  print(f'Coplanar shape0 {i} shape1 {j}')
                  print(f'COM -  face0 {face0.CenterOfMass} face1 {face1.CenterOfMass}')
                  d = face0.CenterOfMass - face1.CenterOfMass
                  print(f'Distance : {d}')
                  #if d == zero:
                  #   return True
        return False
Which is finding 6 Coplanar Faces when I think there should just be 4 and all the CenterOfMass are the same face0, face1

Code: Select all


17:46:18  Coplanar shape0 0 shape1 0
17:46:18  COM -  face0 Vector (-1000.0, -5.820766091346742e-14, -1.0214051826551443e-14) face1 Vector (-1000.0, -5.820766091346742e-14, -1.0214051826551443e-14)
17:46:18  Distance : Vector (0.0, 0.0, 0.0)
17:46:18  Coplanar shape0 1 shape1 1
17:46:18  COM -  face0 Vector (1000.0, -5.820766091346742e-14, -1.0214051826551443e-14) face1 Vector (1000.0, -5.820766091346742e-14, -1.0214051826551443e-14)
17:46:18  Distance : Vector (0.0, 0.0, 0.0)
17:46:18  Coplanar shape0 2 shape1 2
17:46:18  COM -  face0 Vector (-2.910383045673371e-14, -1000.0, -1.0214051826551443e-14) face1 Vector (-2.910383045673371e-14, -1000.0, -1.0214051826551443e-14)
17:46:18  Distance : Vector (0.0, 0.0, 0.0)
17:46:18  Coplanar shape0 3 shape1 3
17:46:18  COM -  face0 Vector (-2.910383045673371e-14, 1000.0, -1.0214051826551443e-14) face1 Vector (-2.910383045673371e-14, 1000.0, -1.0214051826551443e-14)
17:46:18  Distance : Vector (0.0, 0.0, 0.0)
17:46:18  Coplanar shape0 4 shape1 4
17:46:18  COM -  face0 Vector (-1.0214051826551443e-14, -2.910383045673371e-14, -1000.0) face1 Vector (-1.0214051826551443e-14, -2.910383045673371e-14, -1000.0)
17:46:18  Distance : Vector (0.0, 0.0, 0.0)
17:46:18  Coplanar shape0 5 shape1 5
17:46:18  COM -  face0 Vector (-1.0214051826551443e-14, -2.910383045673371e-14, 1000.0) face1 Vector (-1.0214051826551443e-14, -2.910383045673371e-14, 1000.0)
17:46:18  Distance : Vector (0.0, 0.0, 0.0)
Which raises the following questions in my mind?

Does the CenterOfMass for a Face return the center of the Face or the CenterOfMass for the parent Shape?
If I am correct that there should be 4 Coplanar Faces rather than six is the copy and and translate not working

Adjust Shape function is

Code: Select all

    def adjustShape(self, part):
        print("Adjust Shape")
        print(part.Name)
        print(part.OutList)
        if hasattr(part,'LinkedObject'):
           print(f'Linked Object {part.LinkedObject}')
           part = part.getLinkedObject()
           print(part.Name)
           print(part.OutList)
        obj = self.getGDMLObject(part.OutList)
        obj.recompute()
        # Shape is immutable so have to copy
        # Realthunder recommends avoid deep copy
        shape = Part.Shape(obj.Shape)
        print(f'Shape Valid {shape.isValid()}')
        print(dir(shape))
        #return shape
        return shape.translate(part.Placement.Base)
keithsloan52
Veteran
Posts: 2756
Joined: Mon Feb 27, 2012 5:31 pm

Re: Help with computing shared face.

Post by keithsloan52 »

Okay the adjust Shape was not working, using wrong Placement value :-(, I corrected that and now seeing 5(?) coplanar faces.

Code: Select all

18:17:34  Coplanar shape0 1 shape1 0
18:17:34  COM -  face0 Vector (1000.0, -5.820766091346742e-14, -1.0214051826551443e-14) face1 Vector (1000.0, -5.820766091346742e-14, -1.0214051826551443e-14)
18:17:34  Distance : Vector (0.0, 0.0, 0.0)
18:17:34  Coplanar shape0 2 shape1 2
18:17:34  COM -  face0 Vector (-2.910383045673371e-14, -1000.0, -1.0214051826551443e-14) face1 Vector (2000.0, -1000.0, -1.0214051826551443e-14)
18:17:34  Distance : Vector (-2000.0, 0.0, 0.0)
18:17:34  Coplanar shape0 3 shape1 3
18:17:34  COM -  face0 Vector (-2.910383045673371e-14, 1000.0, -1.0214051826551443e-14) face1 Vector (2000.0, 1000.0, -1.0214051826551443e-14)
18:17:34  Distance : Vector (-2000.0, 0.0, 0.0)
18:17:34  Coplanar shape0 4 shape1 4
18:17:34  COM -  face0 Vector (-1.0214051826551443e-14, -2.910383045673371e-14, -1000.0) face1 Vector (2000.0, -2.910383045673371e-14, -1000.0)
18:17:34  Distance : Vector (-2000.0, 0.0, 0.0)
18:17:34  Coplanar shape0 5 shape1 5
18:17:34  COM -  face0 Vector (-1.0214051826551443e-14, -2.910383045673371e-14, 1000.0) face1 Vector (2000.0, -2.910383045673371e-14, 1000.0)
18:17:34  Distance : Vector (-2000.0, 0.0, 0.0)
And now only one face as zero difference between CenterOfMass :-)

Would be happier if I understood why I am seeing 5 coplanar faces.

Question: Is it worth checking for coplanar first or would it be more efficient just to compute difference in CenterOfMass values for all Face pairs.
edwilliams16
Veteran
Posts: 3108
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Help with computing shared face.

Post by edwilliams16 »

A few questions.
  • Are the bordering faces of the two GDMLSolids identical, or can they just have a shared portion?
  • Are the border faces necessarily planar, or could they be, say, cylindrical?
If either of these are yes, a more general approach is required than matching cube faces. One possibility would be to thicken the faces by a small amount and measure the volume of their intersection compared to that of the two operands.

The CenterOfMass and CenterOfGravity (same in FreeCAD AFAIK) of a face are indeed properties of the face. If the bordering faces are identical, then (within numerical error) they will have the same COM. For a curved face the COM will not lie in the face. Having the same COM is a necessary, but not sufficient condition for two faces to be identical, so it is a good test to do first.
keithsloan52
Veteran
Posts: 2756
Joined: Mon Feb 27, 2012 5:31 pm

Re: Help with computing shared face.

Post by keithsloan52 »

edwilliams16 wrote: Sun Jun 26, 2022 6:10 pm A few questions.
  • Are the bordering faces of the two GDMLSolids identical, or can they just have a shared portion?
  • Are the border faces necessarily planar, or could they be, say, cylindrical?
  • Can be shared portion
  • Can be curved surface i.e. cylindrical, i.e. not necessarily planar
edwilliams16
Veteran
Posts: 3108
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Help with computing shared face.

Post by edwilliams16 »

keithsloan52 wrote: Mon Jun 27, 2022 7:26 am
edwilliams16 wrote: Sun Jun 26, 2022 6:10 pm A few questions.
  • Are the bordering faces of the two GDMLSolids identical, or can they just have a shared portion?
  • Are the border faces necessarily planar, or could they be, say, cylindrical?
  • Can be shared portion
  • Can be curved surface i.e. cylindrical, i.e. not necessarily planar
Then we are wasting our time comparing CGs and whether faces are coplanar. Neither of these would be true in general.
I would thicken the faces slightly, intersect them and look at the common volume. Dividing by the thickness would give the common area.
keithsloan52
Veteran
Posts: 2756
Joined: Mon Feb 27, 2012 5:31 pm

Re: Help with computing shared face.

Post by keithsloan52 »

edwilliams16 wrote: Mon Jun 27, 2022 8:58 am
keithsloan52 wrote: Mon Jun 27, 2022 7:26 am
edwilliams16 wrote: Sun Jun 26, 2022 6:10 pm A few questions.
  • Are the bordering faces of the two GDMLSolids identical, or can they just have a shared portion?
  • Are the border faces necessarily planar, or could they be, say, cylindrical?
  • Can be shared portion
  • Can be curved surface i.e. cylindrical, i.e. not necessarily planar
Then we are wasting our time comparing CGs and whether faces are coplanar. Neither of these would be true in general.
I would thicken the faces slightly, intersect them and look at the common volume. Dividing by the thickness would give the common area.
I think I need to loop through all pairs of Faces, if flat then check for coplanar, if not flat somehow check if the same curve,
edwilliams16
Veteran
Posts: 3108
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Help with computing shared face.

Post by edwilliams16 »

If you don't care about speed too much, you could digitize one face surface and do distToShape() to the other one. If there's a common area, you'll have an area of near-zeroes. You could trim the surface using the boundary of the zero patch(es) and get the common face.
keithsloan52
Veteran
Posts: 2756
Joined: Mon Feb 27, 2012 5:31 pm

Re: Help with computing shared face.

Post by keithsloan52 »

Okay if In take an Object in this case a Box.

Code: Select all

>> doc = FreeCAD.ActiveDocument
>>> obj=doc.getObject('GDMLBox_det')
>>> print(dir(obj.Shape.Faces[0]))

Code: Select all

['Area', 'BoundBox', 'CenterOfGravity', 'CenterOfMass', 'CompSolids', 'Compounds', 'Content', 'Edges', 'Faces', 'Length', 'Mass', 'MatrixOfInertia', 'MemSize', 'Module', 'Orientation', 'OuterWire', 'ParameterRange', 'Placement', 'PrincipalProperties', 'ShapeType', 'Shells', 'Solids', 'StaticMoments', 'SubShapes', 'Surface', 'Tag', 'Tolerance', 'TypeId', 'Vertexes', 'Volume', 'Wire', '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__', 'addWire', 'ancestorsOfType', 'applyRotation', 'applyTranslation', 'check', 'childShapes', 'cleaned', 'common', 'complement', 'copy', 'countElement', 'countSubElements', 'curvatureAt', 'curveOnSurface', 'cut', 'cutHoles', 'defeaturing', 'derivative1At', 'derivative2At', 'distToShape', 'dumpContent', 'dumpToString', 'exportBinary', 'exportBrep', 'exportBrepToString', 'exportIges', 'exportStep', 'exportStl', 'extrude', 'findPlane', 'fix', 'fixTolerance', 'fuse', 'generalFuse', 'getAllDerivedFrom', 'getElement', 'getElementTypes', 'getFaces', 'getFacesFromSubElement', 'getLines', 'getLinesFromSubElement', 'getPoints', 'getTolerance', 'getUVNodes', 'globalTolerance', 'hashCode', 'importBinary', 'importBrep', 'importBrepFromString', 'inTolerance', 'isClosed', 'isCoplanar', 'isDerivedFrom', 'isEqual', 'isInfinite', 'isInside', 'isNull', 'isPartOfDomain', 'isPartner', 'isSame', 'isValid', 'limitTolerance', 'makeChamfer', 'makeEvolved', 'makeFillet', 'makeHalfSpace', 'makeOffset', 'makeOffset2D', 'makeOffsetShape', 'makeParallelProjection', 'makePerspectiveProjection', 'makeShapeFromMesh', 'makeThickness', 'makeWires', 'mirror', 'multiFuse', 'normalAt', 'nullify', 'oldFuse', 'optimalBoundingBox', 'overTolerance', 'project', 'proximity', 'read', 'reflectLines', 'removeInternalWires', 'removeShape', 'removeSplitter', 'replaceShape', 'restoreContent', 'reverse', 'reversed', 'revolve', 'rotate', 'rotated', 'scale', 'scaled', 'section', 'sewShape', 'slice', 'slices', 'tangentAt', 'tessellate', 'toNurbs', 'transformGeometry', 'transformShape', 'transformed', 'translate', 'translated', 'validate', 'valueAt', 'writeInventor']
How can I easily test if the Face is flat or curved? curveOnSurface(?)
Post Reply