Extruding along a 3D path (Solved!)

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
SRCAD
Posts: 4
Joined: Sat Nov 18, 2017 11:22 pm

Extruding along a 3D path (Solved!)

Post by SRCAD »

I have a 2D shape that I would like to extrude along a 3D path. I tried a number of methods, and nothing worked.

I've created a wireframe of the 3D object, but I seemingly cannot create faces that are not along planes. I tried makePipeShell and makeLoft (possibly incorrectly) but the resulting objects in no way honored the 2D shape I was trying to extrude and, while it was hard to tell, didn't seem to actually end with the faces parallel either (i.e. my direct object is *not* a semi-circle or fraction thereof, though it is close)

I've attached a python script which generates the wireframe along with my two attempts (each assignment to myObject.Shape represents an attempt).

Any ideas?
Attachments
x.py
(1.73 KiB) Downloaded 73 times
Last edited by SRCAD on Mon Nov 20, 2017 4:11 pm, edited 1 time in total.
User avatar
microelly2
Veteran
Posts: 4688
Joined: Tue Nov 12, 2013 4:06 pm
Contact:

Re: Extruding along a 3D path

Post by microelly2 »

Welcome to the forum,
please read this first https://forum.freecadweb.org/viewtopic.php?f=3&t=2264
we need some information about your environment to support you.
User avatar
Chris_G
Veteran
Posts: 2579
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: Extruding along a 3D path

Post by Chris_G »

Hi,
Since we don't have any information on the FC and OCC version you are running, I don't know if the following code will work for you :

Code: Select all

import Part
import Mesh
from FreeCAD import Base
#import png
#import urllib

App.closeDocument("d")
doc = FreeCAD.newDocument("d")

selfholdoff = 4.25
wall_thickness = 1.75
radius_tube = 12
straight = 95
height = 2.0*straight/3
ringheight = height/2.0


#myObject=App.ActiveDocument.addObject("Part::Feature","Sweep")

def makeArc(x,z):
    V1 = Base.Vector(selfholdoff,radius_tube+wall_thickness+x-.6,ringheight+z)
    V2 = Base.Vector(radius_tube+wall_thickness+x,0,ringheight+z)
    V3 = Base.Vector(selfholdoff,-radius_tube-wall_thickness-x+.6,ringheight+z)
    rp_a = Part.Arc(V1,V2,V3)
    rp_s = Part.Shape([rp_a])
    rp_w = Part.Wire(rp_s.Edges)
    return(rp_w,V1,V3)

points=((0,0),(wall_thickness,wall_thickness),(2*wall_thickness,wall_thickness),(2*wall_thickness,-wall_thickness),(wall_thickness,-wall_thickness))

a1 = makeArc(*points[0])
a2 = makeArc(*points[1])
a3 = makeArc(*points[2])
a4 = makeArc(*points[3])
a5 = makeArc(*points[4])

def makeFaceWire(a1,a2):
    #wire = Part.Wire([a1[0],Part.makeLine(a1[1],a2[1]),a2[0],Part.makeLine(a2[2],a1[2])])
    rs = Part.makeRuledSurface(a1[0],a2[0])
    #Part.show(rs)
    return(rs.Faces[0]) # rs is a shell. We want only the first face

f1 = makeFaceWire(a1,a2)
f2 = makeFaceWire(a2,a3)
f3 = makeFaceWire(a3,a4)
f4 = makeFaceWire(a4,a5)
f5 = makeFaceWire(a5,a1)

w6 = Part.makePolygon([a1[1],a2[1],a3[1],a4[1],a5[1],a1[1]])
f6 = Part.Face(w6)
#Part.show(f6)
w7 = Part.makePolygon([a1[2],a2[2],a3[2],a4[2],a5[2],a1[2]])
f7 = Part.Face(w7)
#Part.show(f7)

sh = Part.Shell([f1,f2,f3,f4,f5,f6,f7])
so = Part.Solid(sh)

Part.show(so)




# ----- Alternate method -------
# Sweeps the 2 end faces along a path

ps = Part.BRepOffsetAPI.MakePipeShell(a1[0])
ps.add(w6)
ps.add(w7)
if ps.isReady():
    ps.build()
    ps.makeSolid()
    Part.show(ps.shape())


SRCAD
Posts: 4
Joined: Sat Nov 18, 2017 11:22 pm

Re: Extruding along a 3D path

Post by SRCAD »

My apologies, I tried to update my post last night with the necessary information but it was held or something so I couldn't do it.

I'll take a look at your suggested code and give it a try. Ruled surfaces. Hmm. I didn't research what those were when I saw passing references to them.

OS: "Fedora release 25 (Twenty Five)"
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.16.Unknown
Build type: Unknown
Python version: 2.7.13
Qt version: 4.8.7
Coin version: 3.1.3
OCC version: 6.8.0.oce-0.17
SRCAD
Posts: 4
Joined: Sat Nov 18, 2017 11:22 pm

Re: Extruding along a 3D path (Solved)

Post by SRCAD »

Thanks Chris_G, both of your techniques worked great!

I imagine I understand what a ruled surface is (I have not stumbled on a good definition of it in my quick searches) and so in my imagination it makes sense that it would work. I'll keep it in the back of my mind the next time I need that sort of correspondence.

I see your second method provides a few critical adjustments to the makePipeShell I tried. I've have to study your example more closely to understand which of the changes had which affect.

Thanks!
LLuoss
Posts: 17
Joined: Mon Apr 29, 2019 6:41 am

Re: Extruding along a 3D path

Post by LLuoss »

Chris_G wrote: Mon Nov 20, 2017 9:12 am Hi,
Since we don't have any information on the FC and OCC version you are running, I don't know if the following code will work for you :

Code: Select all

import Part
import Mesh
from FreeCAD import Base
#import png
#import urllib

App.closeDocument("d")
doc = FreeCAD.newDocument("d")

selfholdoff = 4.25
wall_thickness = 1.75
radius_tube = 12
straight = 95
height = 2.0*straight/3
ringheight = height/2.0


#myObject=App.ActiveDocument.addObject("Part::Feature","Sweep")

def makeArc(x,z):
    V1 = Base.Vector(selfholdoff,radius_tube+wall_thickness+x-.6,ringheight+z)
    V2 = Base.Vector(radius_tube+wall_thickness+x,0,ringheight+z)
    V3 = Base.Vector(selfholdoff,-radius_tube-wall_thickness-x+.6,ringheight+z)
    rp_a = Part.Arc(V1,V2,V3)
    rp_s = Part.Shape([rp_a])
    rp_w = Part.Wire(rp_s.Edges)
    return(rp_w,V1,V3)

points=((0,0),(wall_thickness,wall_thickness),(2*wall_thickness,wall_thickness),(2*wall_thickness,-wall_thickness),(wall_thickness,-wall_thickness))

a1 = makeArc(*points[0])
a2 = makeArc(*points[1])
a3 = makeArc(*points[2])
a4 = makeArc(*points[3])
a5 = makeArc(*points[4])

def makeFaceWire(a1,a2):
    #wire = Part.Wire([a1[0],Part.makeLine(a1[1],a2[1]),a2[0],Part.makeLine(a2[2],a1[2])])
    rs = Part.makeRuledSurface(a1[0],a2[0])
    #Part.show(rs)
    return(rs.Faces[0]) # rs is a shell. We want only the first face

f1 = makeFaceWire(a1,a2)
f2 = makeFaceWire(a2,a3)
f3 = makeFaceWire(a3,a4)
f4 = makeFaceWire(a4,a5)
f5 = makeFaceWire(a5,a1)

w6 = Part.makePolygon([a1[1],a2[1],a3[1],a4[1],a5[1],a1[1]])
f6 = Part.Face(w6)
#Part.show(f6)
w7 = Part.makePolygon([a1[2],a2[2],a3[2],a4[2],a5[2],a1[2]])
f7 = Part.Face(w7)
#Part.show(f7)

sh = Part.Shell([f1,f2,f3,f4,f5,f6,f7])
so = Part.Solid(sh)

Part.show(so)




# ----- Alternate method -------
# Sweeps the 2 end faces along a path

ps = Part.BRepOffsetAPI.MakePipeShell(a1[0])
ps.add(w6)
ps.add(w7)
if ps.isReady():
    ps.build()
    ps.makeSolid()
    Part.show(ps.shape())


ps = Part.BRepOffsetAPI.MakePipeShell。About this method.I have a question,can this method sweep along two paths from one section to another section?I have tried many times,the second pss.add will cover the first.Hope your reply!
User avatar
Chris_G
Veteran
Posts: 2579
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: Extruding along a 3D path (Solved!)

Post by Chris_G »

The "Auxiliary spine" mode is supposed to do this, when its "Contact" option is set to "Contact on border".
Unfortunately, this is broken upstream (in OpenCascade). I have never seen this working.
A workaround is to use the Gordon surface of the Curves workbench.
It builds a surface from a curve network. The guides and profiles must form a grid pattern.
Or you can also give a try at the Surface workbench and its "Filling" tool.
LLuoss
Posts: 17
Joined: Mon Apr 29, 2019 6:41 am

Re: Extruding along a 3D path (Solved!)

Post by LLuoss »

Chris_G wrote: Wed Aug 07, 2019 10:52 am The "Auxiliary spine" mode is supposed to do this, when its "Contact" option is set to "Contact on border".
Unfortunately, this is broken upstream (in OpenCascade). I have never seen this working.
A workaround is to use the Gordon surface of the Curves workbench.
It builds a surface from a curve network. The guides and profiles must form a grid pattern.
Or you can also give a try at the Surface workbench and its "Filling" tool.
Thanks!Do you have an example about how to build a surface from a curve network,I need a .FCMacro file.If you have ,I would really appreciate your offer!
User avatar
Chris_G
Veteran
Posts: 2579
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: Extruding along a 3D path (Solved!)

Post by Chris_G »

Here is an example script, that work in the python console.
Update the Curves workbench, if you had already installed it, because I pushed a fix this morning.

Code: Select all

import FreeCAD
from FreeCAD import Vector
import Part

# Create the curve network

poles0 = [Vector (0.0, 0.0, 0.0), Vector (0.16666666666666666, 0.0, 0.20000000794728598), Vector (0.49999999999999994, 0.0, 0.40000001589457196), Vector (0.8333333333333334, 0.0, 0.20000000794728598), Vector (1.0, 0.0, 0.0)]
weights0 = [1.0, 1.0, 1.0, 1.0, 1.0]
knots0 = [0.0, 0.5830951956177974, 1.1661903912355949]
mults0 = [4, 1, 4]
periodic0 = False
degree0 = 3
rational0 = False
bs0 = Part.BSplineCurve()
bs0.buildFromPolesMultsKnots(poles=poles0, mults=mults0, knots=knots0, periodic=periodic0, degree=degree0, weights=weights0, CheckRational=rational0)
obj0 = FreeCAD.ActiveDocument.addObject("Part::Spline","BSplineCurve0")
obj0.Shape = bs0.toShape()

poles1 = [Vector (0.013121589026499694, 0.7915876947955887, 0.0008571221601094414), Vector (-0.00885599845935274, 0.7914868593215942, 0.40897222572543346), Vector (0.06419121554803943, 0.7914868593215942, 0.9506049970258048), Vector (0.4267428298127499, 0.7914868593215942, 0.5416327713003715), Vector (0.7273027300834656, 0.7914868593215942, 0.0)]
weights1 = [1.0, 1.0, 1.0, 1.0, 1.0]
knots1 = [0.0, 0.7053976507426758, 1.6396089746603792]
mults1 = [4, 1, 4]
periodic1 = False
degree1 = 3
rational1 = False
bs1 = Part.BSplineCurve()
bs1.buildFromPolesMultsKnots(poles=poles1, mults=mults1, knots=knots1, periodic=periodic1, degree=degree1, weights=weights1, CheckRational=rational1)
bs1.getKnots()
obj1 = FreeCAD.ActiveDocument.addObject("Part::Spline","BSplineCurve1")
obj1.Shape = bs1.toShape(bs1.FirstParameter, bs1.LastParameter)

poles2 = [Vector (-0.29265061020851135, 1.7891597747802734, 0.0), Vector (0.556077287533451, 1.7891597747802734, 0.7004100558512543), Vector (1.2192605936714151, 1.7891597747802732, 0.9304442719319388), Vector (1.2656674010425126, 1.7891597747802734, 0.23003421608068433), Vector (1.2394413948059082, 1.7891597747802734, 0.0)]
weights2 = [1.0, 1.0, 1.0, 1.0, 1.0]
knots2 = [0.0, 1.5852100266723423, 2.105837254626154]
mults2 = [4, 1, 4]
periodic2 = False
degree2 = 3
rational2 = False
bs2 = Part.BSplineCurve()
bs2.buildFromPolesMultsKnots(poles=poles2, mults=mults2, knots=knots2, periodic=periodic2, degree=degree2, weights=weights2, CheckRational=rational2)
bs2.getKnots()
obj2 = FreeCAD.ActiveDocument.addObject("Part::Spline","BSplineCurve2")
obj2.Shape = bs2.toShape()

poles3 = [Vector (0.0, 0.0, 0.0), Vector (0.01980706605738829, 0.13102204117622993, 0.03582234726635581), Vector (0.04193204614098622, 0.39521243838553644, 0.05609202982516635), Vector (0.011570412468109364, 1.0063177946409716, -0.02655385582891836), Vector (-0.12865621642847969, 1.4740525911095985, -0.12251780016751808), Vector (-0.29265061020851135, 1.7891597747802734, 0.0)]
weights3 = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
knots3 = [0.0, 0.55, 1.841346800327301]
mults3 = [4, 2, 4]
periodic3 = False
degree3 = 3
rational3 = False
bs3 = Part.BSplineCurve()
bs3.buildFromPolesMultsKnots(poles=poles3, mults=mults3, knots=knots3, periodic=periodic3, degree=degree3, weights=weights3, CheckRational=rational3)
obj3 = FreeCAD.ActiveDocument.addObject("Part::Spline","BSplineCurve3")
obj3.Shape = bs3.toShape()

FreeCAD.ActiveDocument.recompute()

poles4 = [Vector (0.37568899989128113, 0.0, 0.2814561426639557), Vector (0.1979298550637957, 0.2528165565557051, 0.5073158012737045), Vector (0.012426622785748864, 0.8217413994502759, 0.8116662306235015), Vector (0.25350408566703514, 1.4418752936204768, 0.7220463662761115), Vector (0.5054633617401123, 1.7891597747802734, 0.5606870651245117)]
weights4 = [1.0, 1.0, 1.0, 1.0, 1.0]
knots4 = [0.0, 0.9339859674161192, 2.0140618136101445]
mults4 = [4, 1, 4]
periodic4 = False
degree4 = 3
rational4 = False
bs4 = Part.BSplineCurve()
bs4.buildFromPolesMultsKnots(poles=poles4, mults=mults4, knots=knots4, periodic=periodic4, degree=degree4, weights=weights4, CheckRational=rational4)
obj4 = FreeCAD.ActiveDocument.addObject("Part::Spline","BSplineCurve4")
obj4.Shape = bs4.toShape()

poles5 = [Vector (1.0, 0.0, 0.0), Vector (0.7962455246105475, 0.23471487235329058, -0.07387134852685648), Vector (0.6630578583047347, 0.6931604531973199, -0.02306488701337041), Vector (0.8347851190761894, 1.346445916688191, 0.09673176665963677), Vector (1.0782930244160058, 1.6595823128097014, 0.07573943536620759), Vector (1.2394413948059082, 1.7891597747802734, 0.0)]
weights5 = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
knots5 = [0.0, 0.837147057056427, 1.3702200651168823, 1.9922663569450378]
mults5 = [4, 1, 1, 4]
periodic5 = False
degree5 = 3
rational5 = False
bs5 = Part.BSplineCurve()
bs5.buildFromPolesMultsKnots(poles=poles5, mults=mults5, knots=knots5, periodic=periodic5, degree=degree5, weights=weights5, CheckRational=rational5)
obj5 = FreeCAD.ActiveDocument.addObject("Part::Spline","BSplineCurve5")
obj5.Shape = bs5.toShape()


# Create the Gordon surface

import gordon
gordon = gordon.InterpolateCurveNetwork([bs0,bs1,bs2],[bs3,bs4,bs5],0.1,0.001)
Part.show(gordon.surface().toShape())

LLuoss
Posts: 17
Joined: Mon Apr 29, 2019 6:41 am

Re: Extruding along a 3D path (Solved!)

Post by LLuoss »

Chris_G wrote: Fri Aug 09, 2019 11:57 am Here is an example script, that work in the python console.
Update the Curves workbench, if you had already installed it, because I pushed a fix this morning.

Code: Select all

import FreeCAD
from FreeCAD import Vector
import Part

# Create the curve network

poles0 = [Vector (0.0, 0.0, 0.0), Vector (0.16666666666666666, 0.0, 0.20000000794728598), Vector (0.49999999999999994, 0.0, 0.40000001589457196), Vector (0.8333333333333334, 0.0, 0.20000000794728598), Vector (1.0, 0.0, 0.0)]
weights0 = [1.0, 1.0, 1.0, 1.0, 1.0]
knots0 = [0.0, 0.5830951956177974, 1.1661903912355949]
mults0 = [4, 1, 4]
periodic0 = False
degree0 = 3
rational0 = False
bs0 = Part.BSplineCurve()
bs0.buildFromPolesMultsKnots(poles=poles0, mults=mults0, knots=knots0, periodic=periodic0, degree=degree0, weights=weights0, CheckRational=rational0)
obj0 = FreeCAD.ActiveDocument.addObject("Part::Spline","BSplineCurve0")
obj0.Shape = bs0.toShape()

poles1 = [Vector (0.013121589026499694, 0.7915876947955887, 0.0008571221601094414), Vector (-0.00885599845935274, 0.7914868593215942, 0.40897222572543346), Vector (0.06419121554803943, 0.7914868593215942, 0.9506049970258048), Vector (0.4267428298127499, 0.7914868593215942, 0.5416327713003715), Vector (0.7273027300834656, 0.7914868593215942, 0.0)]
weights1 = [1.0, 1.0, 1.0, 1.0, 1.0]
knots1 = [0.0, 0.7053976507426758, 1.6396089746603792]
mults1 = [4, 1, 4]
periodic1 = False
degree1 = 3
rational1 = False
bs1 = Part.BSplineCurve()
bs1.buildFromPolesMultsKnots(poles=poles1, mults=mults1, knots=knots1, periodic=periodic1, degree=degree1, weights=weights1, CheckRational=rational1)
bs1.getKnots()
obj1 = FreeCAD.ActiveDocument.addObject("Part::Spline","BSplineCurve1")
obj1.Shape = bs1.toShape(bs1.FirstParameter, bs1.LastParameter)

poles2 = [Vector (-0.29265061020851135, 1.7891597747802734, 0.0), Vector (0.556077287533451, 1.7891597747802734, 0.7004100558512543), Vector (1.2192605936714151, 1.7891597747802732, 0.9304442719319388), Vector (1.2656674010425126, 1.7891597747802734, 0.23003421608068433), Vector (1.2394413948059082, 1.7891597747802734, 0.0)]
weights2 = [1.0, 1.0, 1.0, 1.0, 1.0]
knots2 = [0.0, 1.5852100266723423, 2.105837254626154]
mults2 = [4, 1, 4]
periodic2 = False
degree2 = 3
rational2 = False
bs2 = Part.BSplineCurve()
bs2.buildFromPolesMultsKnots(poles=poles2, mults=mults2, knots=knots2, periodic=periodic2, degree=degree2, weights=weights2, CheckRational=rational2)
bs2.getKnots()
obj2 = FreeCAD.ActiveDocument.addObject("Part::Spline","BSplineCurve2")
obj2.Shape = bs2.toShape()

poles3 = [Vector (0.0, 0.0, 0.0), Vector (0.01980706605738829, 0.13102204117622993, 0.03582234726635581), Vector (0.04193204614098622, 0.39521243838553644, 0.05609202982516635), Vector (0.011570412468109364, 1.0063177946409716, -0.02655385582891836), Vector (-0.12865621642847969, 1.4740525911095985, -0.12251780016751808), Vector (-0.29265061020851135, 1.7891597747802734, 0.0)]
weights3 = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
knots3 = [0.0, 0.55, 1.841346800327301]
mults3 = [4, 2, 4]
periodic3 = False
degree3 = 3
rational3 = False
bs3 = Part.BSplineCurve()
bs3.buildFromPolesMultsKnots(poles=poles3, mults=mults3, knots=knots3, periodic=periodic3, degree=degree3, weights=weights3, CheckRational=rational3)
obj3 = FreeCAD.ActiveDocument.addObject("Part::Spline","BSplineCurve3")
obj3.Shape = bs3.toShape()

FreeCAD.ActiveDocument.recompute()

poles4 = [Vector (0.37568899989128113, 0.0, 0.2814561426639557), Vector (0.1979298550637957, 0.2528165565557051, 0.5073158012737045), Vector (0.012426622785748864, 0.8217413994502759, 0.8116662306235015), Vector (0.25350408566703514, 1.4418752936204768, 0.7220463662761115), Vector (0.5054633617401123, 1.7891597747802734, 0.5606870651245117)]
weights4 = [1.0, 1.0, 1.0, 1.0, 1.0]
knots4 = [0.0, 0.9339859674161192, 2.0140618136101445]
mults4 = [4, 1, 4]
periodic4 = False
degree4 = 3
rational4 = False
bs4 = Part.BSplineCurve()
bs4.buildFromPolesMultsKnots(poles=poles4, mults=mults4, knots=knots4, periodic=periodic4, degree=degree4, weights=weights4, CheckRational=rational4)
obj4 = FreeCAD.ActiveDocument.addObject("Part::Spline","BSplineCurve4")
obj4.Shape = bs4.toShape()

poles5 = [Vector (1.0, 0.0, 0.0), Vector (0.7962455246105475, 0.23471487235329058, -0.07387134852685648), Vector (0.6630578583047347, 0.6931604531973199, -0.02306488701337041), Vector (0.8347851190761894, 1.346445916688191, 0.09673176665963677), Vector (1.0782930244160058, 1.6595823128097014, 0.07573943536620759), Vector (1.2394413948059082, 1.7891597747802734, 0.0)]
weights5 = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
knots5 = [0.0, 0.837147057056427, 1.3702200651168823, 1.9922663569450378]
mults5 = [4, 1, 1, 4]
periodic5 = False
degree5 = 3
rational5 = False
bs5 = Part.BSplineCurve()
bs5.buildFromPolesMultsKnots(poles=poles5, mults=mults5, knots=knots5, periodic=periodic5, degree=degree5, weights=weights5, CheckRational=rational5)
obj5 = FreeCAD.ActiveDocument.addObject("Part::Spline","BSplineCurve5")
obj5.Shape = bs5.toShape()


# Create the Gordon surface

import gordon
gordon = gordon.InterpolateCurveNetwork([bs0,bs1,bs2],[bs3,bs4,bs5],0.1,0.001)
Part.show(gordon.surface().toShape())

Can this work in version 0.16?
Post Reply