Boolean cutting of tubes not always working [Solved]

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Jee-Bee
Veteran
Posts: 2566
Joined: Tue Jun 16, 2015 10:32 am
Location: Netherlands

Re: Boolean cutting of tubes not always working [Solved]

Post by Jee-Bee »

FreeCAD is not the only CAD package who have difficulties with thicknesses close to zero ... I have experienced with other commercial ones too
Doug
Posts: 46
Joined: Sun Feb 26, 2017 8:51 pm

Re: Boolean cutting of tubes not always working [Solved]

Post by Doug »

TheMarkster wrote: Wed Jun 26, 2019 1:47 am I wonder if the issue could be the 2 seamlines are intersecting? If you view them in wireframe mode you can see this better. If I add this line just before the line where the cut is made (has the effect of moving one of the pipes up in z direction by .0000001 mm)

Code: Select all

d.Member1Tube.Placement.Base.z += .0000001
it seems to work.
Hi TheMarkster,

Wow :o - it is interesting that the coping is sensitive to such a tiny movement (100 pm) ! I will try this solution on some of the other tubes that I was having trouble with. Thank you for the suggestion :)

Cheers,
Doug
TheMarkster
Veteran
Posts: 5513
Joined: Thu Apr 05, 2018 1:53 am

Re: Boolean cutting of tubes not always working [Solved]

Post by TheMarkster »

Doug wrote: Wed Jun 26, 2019 7:14 pm
Hi TheMarkster,

Wow :o - it is interesting that the coping is sensitive to such a tiny movement (100 pm) ! I will try this solution on some of the other tubes that I was having trouble with. Thank you for the suggestion :)

Cheers,
Doug
Yeah, it's only moving it slightly less than twice the diameter of a hydrogen atom.
Doug
Posts: 46
Joined: Sun Feb 26, 2017 8:51 pm

Re: Boolean cutting of tubes not always working [Solved]

Post by Doug »

Hi TheMarkster,

I made a very small movement to all the tubes in my larger model that weren't coping properly and - voilà - it worked! Now I have two workable options. Thanks again for your help :)

Cheers,
Doug
TheMarkster
Veteran
Posts: 5513
Joined: Thu Apr 05, 2018 1:53 am

Re: Boolean cutting of tubes not always working [Solved]

Post by TheMarkster »

Doug wrote: Mon Jul 01, 2019 3:30 am Hi TheMarkster,

I made a very small movement to all the tubes in my larger model that weren't coping properly and - voilà - it worked! Now I have two workable options. Thanks again for your help :)

Cheers,
Doug
Cool deal. Here's a 3rd option that doesn't involve moving, but rather rotating. I added a Part.show() so the wire that gets rotated is displayed on the screen. By rotating these EndWire objects the seamlines no longer intercept with the other tube. At least, that's my theory. Could also just be modifying the placement has the effect of not just rotating, but also moving the EndWire objects ever so slightly.

full code:

Code: Select all

import os
import sys
import Part
import PartDesign
import Draft
import DraftGeomUtils
import math
import numpy as np
import time
from FreeCAD import Base
from Part import Wire, Face, Solid
from math import cos, sin, tan, radians, asin, acos, atan, atan2, degrees

rotationCount = 0

d = App.newDocument("Tube_Cutting")
g = FreeCADGui.ActiveDocument

V = App.Vector
x = V(1,0,0)
y = V(0,1,0)
z = V(0,0,1)
Origin = V(0,0,0)

def makeMember(MemberName, MemberCL, MemberOR, MemberIR, Transparency, TubeVisibility=True):
    # print('MakeMember: ',MemberName)
    TubeName = MemberName+'Tube'
    OuterName = MemberName+'Outer'
    MemberOuterCyl = MemberOuter(MemberCL, MemberOR)
    MemberInnerCyl = MemberOuter(MemberCL, MemberIR)
    MemberTube = MemberOuterCyl.cut(MemberInnerCyl)
    d.addObject("Part::Feature",OuterName).Shape = Part.Solid(MemberOuterCyl)
    d.addObject("Part::Feature",TubeName).Shape = MemberTube
    MemberGUI = getattr(g,TubeName)
    MemberGUI.Transparency=Transparency
    MemberGUI.Visibility=TubeVisibility
    MemberOuterGUI = getattr(g,OuterName)
    MemberOuterGUI.Visibility=False
    return(MemberTube)

def MemberOuter(MemberCL, MemberOR):
    global rotationCount
    # print('MemberOuter')
    OuterShellSegmentL = []
    StartP = MemberCL.Vertexes[0].Point
    EndP = MemberCL.Vertexes[-1].Point
    MemberLen = StartP.distanceToPoint(EndP)
    Tolerance = MemberLen/10**6
    
    for CLEdge in MemberCL.Edges:
        OuterShellSegmentL.append((Part.makeTube(CLEdge,MemberOR)))
    # print(OuterShell)
    EndWire=makeEndFace(OuterShellSegmentL[0], StartP, Tolerance).OuterWire
    rotationCount += 1
    if rotationCount == 1 or rotationCount == 2: #rotate only these 2 so the seamlines don't intersect the other tube
        EndWire.Placement = App.Placement(App.Vector(-124.338,-113.23,176.579),App.Rotation(App.Vector(-0.569414,0.813173,0.120487),10))
        Part.show(EndWire)
    Tube = Part.Wire(MemberCL).makePipeShell([EndWire],True,True)
    
    return(Tube)

def makeEndFace(Shell, StartP, Tolerance):
    # print(MemberName)
    for ShellEdge in Shell.Edges:
        # print('ShellEdge ',ShellEdge)
        if ShellEdge.Closed:    #Found end edge
            # print('Closed Edge')
            CircularFace = Part.Face(Part.Wire(ShellEdge))   # Make circular end face
            if CircularFace.isInside(StartP,Tolerance,True): #Check if face contains start point
                # print('StartFace')
                return(CircularFace)
            else:
                print('No face found')
    return()
  
MemberVisibility = False
MemberTransparency = 0
CLVisibility = False

MemberOR = 35/2
MemberIR = 33.5/2

MemberStart = V(1430.0, -415.3,  909.0)
MemberEnd = V(804.2,  478.4,  897.0)
MemberMid = V((MemberStart+MemberEnd)/2+V(0,0,36))
MemberCL = Part.Wire(Part.Arc(MemberStart,MemberMid,MemberEnd).toShape())
d.addObject("Part::Feature",'MemberCL').Shape = MemberCL
MemberTube = makeMember('Member', MemberCL, MemberOR, MemberIR, MemberTransparency, MemberVisibility)

d.addObject("Part::Feature",'Member1CL').Shape = d.MemberCL.Shape.mirror(Origin,y)
Member1Tube = makeMember('Member1', d.Member1CL.Shape, MemberOR, MemberIR, MemberTransparency, MemberVisibility)
   
print('Cut tubes')
# d.Member1Tube.Placement.Base.z += .0000001
Member1Cut = d.Member1Tube.Shape.cut(d.MemberOuter.Shape)
d.addObject("Part::Feature",'Member1Cut').Shape = Member1Cut

g.MemberCL.Visibility=CLVisibility
g.Member1CL.Visibility=CLVisibility
# g.MemberTube.Visibility=False
# g.Member1Tube.Visibility=False
g.activeView().viewIsometric()
g.ActiveView.fitAll()
d.recompute()
diff.txt

Code: Select all

13a14,15
> rotationCount = 0
> 
39a42
>     global rotationCount
50a54,57
>     rotationCount += 1
>     if rotationCount == 1 or rotationCount == 2: #rotate only these 2 so the seamlines don't intersect the other tube
>         EndWire.Placement = App.Placement(App.Vector(-124.338,-113.23,176.579),App.Rotation(App.Vector(-0.569414,0.813173,0.120487),10))
>         Part.show(EndWire)
87c94
< d.Member1Tube.Placement.Base.z += .0000001
---
> # d.Member1Tube.Placement.Base.z += .0000001

Here is how I calculated the values for the Placement property so the wire would be rotated about its own center rather than about the coordinate system's center.

phpBB [video]



First I made the EndWires visible using Part.show() in the code. Then I added a Part.Vertex using the GUI and mapped its attachment to the wire, concentric mode so it moves to the center of the wire and serves as a reference point for the next step. Then using the Placement task I selected 3 points: first the center point, then the seamline point, then any arbitrary point along the circumference of the wire. Then click Selected Points button which has the effect of placing the center coordinates in the Center boxes and also generating a custom axis of rotation. I rotated 10 degrees along that axis, hit OK, and copy/pasted from the python console. Due to the inherent inaccuracies of the way floating point numbers are stored in the computer it's almost certainly to be the case that there is also some slight motion in the x,y, and z directions in addition to the rotation.
Doug
Posts: 46
Joined: Sun Feb 26, 2017 8:51 pm

Re: Boolean cutting of tubes not always working [Solved]

Post by Doug »

TheMarkster wrote: Mon Jul 01, 2019 8:07 am
Cool deal. Here's a 3rd option that doesn't involve moving, but rather rotating. I added a Part.show() so the wire that gets rotated is displayed on the screen. By rotating these EndWire objects the seamlines no longer intercept with the other tube. At least, that's my theory. Could also just be modifying the placement has the effect of not just rotating, but also moving the EndWire objects ever so slightly.
Hi TheMarkster,

You sir, have outdone yourself by providing me with not just one, but two workable solutions to this problem! In some ways, I like your second solution even more than your first because it involves no change to the object, versus the first one which had a tiny change. It's a very clever solution. My hat's off to you. :D

Cheers,
Doug
Post Reply