Topological data scripting/sv

Introduktion
Här kommer vi att förklara hur du kontrollerar Del Modulen direkt från FreeCADs python tolk, eller från ett externt skript. Titta igenom Skript avsnittet och FreeCAD Skript grunder sidorna om du behöver mer information om hur python skript fungerar i FreeCAD.

För att kunna använda Delmodulens funktioner så måste du ladda Del modulen i tolken:

Klass Diagram
Detta är en UML översikt över de viktigaste klasserna i Del modulen:



Geometri
De geomtriska objekten är byggblocken för alla topologiska objekt:


 * GEOM Basklass för geometriska objekt


 * LINE En rak linje i 3D, definierad av en start- och en slutpunkt


 * CIRCLE Cirkel eller cirkelsegment som definieras av en centrumpunkt, start- och en slutpunkt


 * ...... Och snart lite mer ;-)

Topologi
Följande topologiska datatyper finns tillgängliga:


 * COMPOUND En grupp av valfri typ av topologiska objekt.
 * COMPSOLID En kompositsolid är ett set av solider ihopkopplade genom dess ytor. Det expanderar begreppen WIRE och SHELL till solider.
 * SOLID En rymd som är begränsad av skal. Den är tredimensionell.
 * SHELL Ett set av ytor ihopkopplade genom dess kanter. Ett skal kan vara öppet eller slutet.
 * FACE I 2D så är det en del av ett plan; i 3D är det en del av en yta. Dess geometri är begränsad (trimmad) av konturer. Den är tvådimensionell.
 * WIRE Ett set av kanter som är ihopkopplade genom dess hörn. Det kan vara en öppen eller sluten kontur beroende på om kanterna är ihoplänkade eller inte.
 * EDGE Ett topologiskt element som motsvarar en begränsad kurva. En kant är vanligtvis begränsad av hörn. Det har en dimension.
 * VERTEX Ett topologiskt element som motsvarar en punkt. Dess dimension är noll.
 * SHAPE En allmän term som täcker allt ovan.

Kort beskrivning
Du kan lätt skapa enkla topologiska objekt med "make..." metoden från Del Modulen:

b = Part.makeBox(100,100,100) Part.show(b)

Några andra make... metoder fom finns:


 * makeBox(l,w,h,[p,d]) -- Skapa en låda placerad i p och pekar i riktningen d med dimensionerna (l,w,h). Som standard är p Vektor(0,0,0) och d är Vektor(0,0,1)
 * makeCircle(radius,[p,d,angle1,angle2]) -- Skapa en cirkel med en given radie. Som standard är p Vektor(0,0,0), d är Vektor(0,0,1) angle1=0 och angle2=360
 * makeCompound(list) -- Skapar en compound från en lista med former (shapes)
 * makeCone(radius1,radius2,height,[p,d,angle]) -- Skapa en kon med given radie och höjd. Som standard är p Vektor(0,0,0), d är Vektor(0,0,1) och angle=360
 * makeCylinder(radius,height,[p,d,angle]) -- Skapa en cylinder med given radie och höjd. Som standard är p Vektor(0,0,0), d är Vektor(0,0,1) och angle=360
 * makeLine((x1,y1,z1),(x2,y2,z2)) -- Skapa en linje mellan två punkter
 * makePlane(length,width,[p,d]) -- Skapa ett plan med längd och bredd. med given radie och höjd. Som standard är p Vektor(0,0,0), och d är Vektor(0,0,1)
 * makePolygon(list) -- Skapa en polygon från en lista med punkter
 * makeSphere(radius,[p,d,angle1,angle2,angle3]) -- Skapa en sfär med given radie. Som standard är p Vektor(0,0,0), d Vektor(0,0,1), angle1=0, angle2=90 och angle3=360
 * makeTorus(radius1,radius2,[p,d,angle1,angle2,angle3]) -- Skapa en torus med given radie. Som standard är p Vektor(0,0,0), d Vektor(0,0,1), angle1=0, angle2=360 och angle3=360

Detaljerade förklaringar
Importera först följande:

>>> import Part >>> from FreeCAD import Base

Hur skapar man ett hörn?
vertex är en punkt skapad vid x=1,y=0,z=0

givet ett hörn (vertex) objekt, så kan du hitta dess placering så här:

Hur skapar man en kant?
En kant är inget annat än en linje med två hörn:

Notera: Du kan inte skapa en kant som passerar två hörn.

Du kan hitta en kants längd och centrum så här:

Hur skapar man en tråd?
en tråd kan skapas från en lista med kanter eller en lista med trådar:

Part.show(wire3) kommer att visa fyra linjer som bildar en kvadrat:

Hur skapar man en yta?
Endast ytor som skapats av stängda trådar är giltiga.

I detta exempel, så är wire3 en stängd tråd men wire2 är inte det (se ovan)

Endast ytor har en area, inte trådar eller kanter.

Hur skapar man en cirkel?
circle = Part.makeCircle(radius,[center,dir_normal,angle1,angle2]) -- Skapa en cirkel med en given radie

Som standard är, center=Vektor(0,0,0), dir_normal=Vektor(0,0,1), angle1=0 och angle2=360.

En cirkel kan skapas så här:

Om du vill skapa den vid en viss position och med en viss riktning

cirkeln kommer att skapas med en distans 10 från nollpunkten i x och kommer att vara vänd mot x axeln.

Notera: makeCircle accepterar endast Base.Vector men inte tupler.

Du kan också skapa en cirkelbåge genom att ge start- och slutvinkel:

Både arc1 och arc2 kommer tillsammans skapa en cirkel.

Vinklar ska anges i grader, om du har radianer, konvertera det genom att använda formeln:

Grader = radianer * 180/PI

eller genom att använda python's math modul (efter att du importerat math, förstås):

grader = math.degrees(radianer)

Hur skapar man en cirkelbåge längs punkter?
Olyckligtvis så finns det ingen makeArc funktion men vi har Part.Arc funktionen för att skapa en cirkelbåge längs tre punkter.

Det kan antas vara en cirkelbåge som förenar start- och slutpunkt genom mittenpunkten.

Part.Arc skapar ett arc objekt på vilken .toShape måste kallas för att få kant objektet,

vilket i allmänhet skapas av makeLine eller makeCircle

Notera: Arc accepterar endast Base.Vector för punkter men inte tupler.

arc_edge är vad vi vill ha, vilken vi kan visa med Part.show(arc_edge).

Om du vill ha en liten del av en cirkel som en cirkelbåge, så är det också möjligt:

Hur skapar man en polygon eller linje längs punkter?
En linje längs multipla punkter är inget annat än att skapa en tråd med multipla kanter.

makePolygon funktionen tar en lista med punkter och skapar en tråd längs dessa punkter:

Hur skapar man ett plan?
Ett plan är en platt yta, alltså en yta i 2D

makePlane(length,width,[start_pnt,dir_normal]) -- Skapa ett plan

Som standard start_pnt=Vector(0,0,0) och dir_normal=Vector(0,0,1).

dir_normal=Vector(0,0,1) kommer att skapa ett plan vinkelrätt mot z axeln.

dir_normal=Vector(1,0,0) kommer att skapa ett plan vinkelrätt mot x axeln:

BoundBox är en kub som omsluter planet med en diagonal som startar vid (3,0,0) och slutar vid (5,0,2).

Här ar BoundBox tjockleken i y axeln noll.

Notera: makePlane accepterar endast Base.Vector för start_pnt och dir_normal men inte tupler

Hur skapar man en ellips?
För att skapa en ellips så finns det flera sätt: Part.Ellipse

Skapar en ellips med majorradie 2 och minorradie 1 med

centrum i (0,0,0)

Part.Ellipse(Ellipse)

skapa en kopia på den givna ellipsen

Part.Ellipse(S1,S2,Center)

Skapar en ellips centrerad på punkten Center, där ellipsens plan är definierad av Center, S1 och S2, dess majoraxel är definierad av Center och S1, dess majorradie är avståndet mellan Center och S1, och dess minorradie är avståndet mellan S2 och majoraxeln.

Part.Ellipse(Center,MajorRadius,MinorRadius)

Skapar en ellips med major och minor radierna MajorRadius och MinorRadius, och är placerad i det plan som definieras av Center och normalen (0,0,1)

I koden ovan så har vi gett S1, S2 och centrum. I likhet med Arc, så skapar Ellipse också ett ellipsobjekt men inte kant, så vi behöver konvertera den till en kant genom att använda toShape för att visa den

Note: Arc accepterar endast Base.Vector för punkter men inte tupler

För Ellipse konstruktören ovan så har vi gett center, MajorRadius och MinorRadius

Hur skapar man en Torus?
makeTorus(radius1,radius2,[pnt,dir,angle1,angle2,angle]) -- Skapa en torus med given radie och vinklar.

Som standard är pnt=Vector(0,0,0),dir=Vector(0,0,1),angle1=0,angle1=360 och angle=360

anse torus som en liten cirkel som sveper längs en stor cirkel:

radius1 den stora cirkelns radie, radius2 är den lilla cirkelns radie, pnt torusens centrum och dir är normalriktningen. angle1 och angle2 är vinklar i radianer för den lilla cirkeln, för att skapa en cirkelbåge den sista parametervinkeln är för att sektionera torusen:

Ovanstående kod kommer att skapa en torus med diametern 20(radie 10) och tjocklek 4(lilla cirkelradien 2)

Ovanstående kod kommer att skapa en bit av en torus

Ovanstående kod kommer att skapa en semi torus, endast den sista parametern är ändrad d.v.s. vinkeln och de kvarvarande vinklarna är standardvärden.

Genom att ge vinkeln 180 så kommer en halvtorus att skapas

Hur skapar man en låda eller en kub?
makeBox(length,width,height,[pnt,dir]) -- Skapar en låda placerad i pnt med dimensionerna (längd,bredd,höjd)

Som standard är pnt=Vektor(0,0,0) och dir=Vektor(0,0,1)

Hur skapar man en sfär?
makeSphere(radius,[pnt, dir, angle1,angle2,angle3]) -- Skapa en sför med given radie.

Som standard är pnt=Vektor(0,0,0), dir=Vektor(0,0,1), angle1=-90, angle2=90 och angle3=360.

angle1 och angle2 är sfärens vertikala minimum och maximum ,

angle3 sfärdiametern

Hur skapar men en Cylinder?
makeCylinder(radius,height,[pnt,dir,angle]) -- skapa en cylinder med given radie och höjd

Som standard är pnt=Vektor(0,0,0),dir=Vektor(0,0,1) och angle=360

Hur skapar man en Kon?
makeCone(radius1,radius2,height,[pnt,dir,angle]) -- skapa en kon med given radie och höjd

Som standard är pnt=Vector(0,0,0), dir=Vector(0,0,1) och angle=360

Hur klipper man ut en form från en annan?
cut(...)

Skillnaden mellan denna och en given topografisk form.

Hur får man det gemensamma mellan två former?
common(...)

Skärning mellan denna och en given topografisk form.

Hur förenar man två former?
fuse(...)

Förening av denna och en given topografisk form.

Hur man sektionerar en solid med given form?
section(...)

Sektionering av denna med en given topografisk form.

Kommer att returnera en skärningskurva, en compound med kanter

Utforska former
du kan lätt utforska den topologiska datastrukturen:

import Part b = Part.makeBox(100,100,100) b.Wires w = b.Wires[0] w w.Wires w.Vertexes Part.show(w) w.Edges e = w.Edges[0] e.Vertexes v = e.Vertexes[0] v.Point

Genom att skriva in ovanstående rader i python tolken, kommer du att få en god förståelse av Del objektens struktur. Här skapade vårt makeBox kommando en solid form. Denna solid, liksom alla Del solider, innehåller ytor. Ytor innehåller alltid trådar, vilka är listor på kanter som gränsar till ytan. Varje yta har exakt en stängd tråd. I tråden, så kan vi titta på varje kant separat, och inuti varje kant, så kan vi se hörnen. Raka kanter har förstås endast två hörn. Del Hörn är OCC former, men de har ett punktattribut vilket returnerar en snygg FreeCAD Vektor.

Utforska Kanter
I fallet Kanter, vilken är en godtycklig kurva, så är det mycket troligt att du vill göra en diskretisering. I FreeCAD så är kanterna parametriserade av dess längder. Det innebär att du kan gå en kant/kurva genom dess längd:

import Part anEdge = Part.makeBox(100,100,100).Edges[0] # skapa en låda med 100mm kantlängd och få den första kanten print anEdge.Length # hämta kantens längd i mm (modelleringsenheten)

Nu kan du komma åt många av kantens egenskaper genom att använda längden som en position. Det betyder att om

kanten är 100mm lång så är startpositionen 0 och slutpositionen 100.

anEdge.tangentAt(0.0)     # tangent riktning vid starten anEdge.valueAt(0.0)       # Punkt vid starten anEdge.valueAt(100.0)     # Punkt vid slutet av kanten anEdge.derivative1At(50.0) # kurvans första derivativ i mitten anEdge.derivative2At(50.0) # kurvans andra derivativ i mitten anEdge.derivative3At(50.0) # kurvans tredje derivativ i mitten anEdge.centerOfCurvatureAt(50) # kurvaturens centrum för den positionen anEdge.curvatureAt(50.0)  # kurvaturen anEdge.normalAt(50)       # normalvektor vid den positionen (om den är definierad)

Använda valet
Här ser vi nu hur vi kan använda det val som användaren gjorde i visaren.

Först av allt så skapar vi en låda och visar den i visaren

import Part Part.show(Part.makeBox(100,100,100)) Gui.SendMsgToActiveView("ViewFit")

Välj nu några ytor eller kanter. Med detta skript kan du

iterera alla valda objekt och deras delelement:

for o in Gui.Selection.getSelectionEx: print o.ObjectName for s in o.SubElementNames: print "name: ",s for s in o.SubObjects: print "object: ",s

Välj några kanter och detta skript kommer att beräkna längden:

length = 0.0 for o in Gui.Selection.getSelectionEx: for s in o.SubObjects: length += s.Length print "Längd på de valda kanterna:" ,length

Skapa simpel topologi


Vi ska nu skapa en topologi genom att konstruera den utifrån enklare geometri. Som ett studiefall så använder vi en del som syns i bilden vilken består av fyra hörn, två cirklar och två linjer.

Skapa Geometri
Först så måste vi skapa de distinkt geometriska delarna av denna tråd. Och vi måste ta hänsyn till att hörnen på de geometriska delarna är på samma position. Annars kanske vi inte kan koppla ihop de geometriska delarna till en topologi!

Så vi skapar punkterna först:

from FreeCAD import Base V1 = Base.Vector(0,10,0) V2 = Base.Vector(30,10,0) V3 = Base.Vector(30,-10,0) V4 = Base.Vector(0,-10,0)

Cirkelbåge


För att skapa en cirkelbåge så skapar vi en hjälppunkt och skapar cirkelbågen genom tre punkter: VC1 = Base.Vector(-10,0,0) C1 = Part.Arc(V1,VC1,V4) VC2 = Base.Vector(40,0,0) C2 = Part.Arc(V2,VC2,V3)
 * 1) och den andra

Linje
Linjen kan skapas mycket lätt ur punkterna: L1 = Part.Line(V1,V2) L2 = Part.Line(V4,V3)
 * 1) och den andra

Sätta ihop allt
Det sista steget är att sätta ihop den geometriska grundelementen och baka en topologisk form: S1 = Part.Shape([C1,C2,L1,L2])

Skapa ett prisma
Extrudera nu tråden i en riktning och skapa en äkta 3D form: W = Part.Wire(S1.Edges) P = W.extrude(Base.Vector(0,0,10))

OCC flaskan
Ett typiskt exempel som finns på OpenCasCade Startsida är hur man bygger en flaska.

Detta är en god övning även för FreeCAD. Du kan faktiskt följa vårt exempel nedan och OCC sidan samtidigt, du kommer att få en god förståelse om hur OCC strukturer är implementerade i FreeCAD.

Hela skriptet nedan är även inkluderat i FreeCAD installationen (i Mod/Part mappen) och kan anropas från python tolken genom att skriva:

import Part import MakeBottle bottle = MakeBottle.makeBottle Part.show(bottle)

Det kompletta skriptet
Här är det kompletta MakeBottle skriptet:

import Part, FreeCAD, math from FreeCAD import Base def makeBottle(myWidth=50.0, myHeight=70.0, myThickness=30.0): aPnt1=Base.Vector(-myWidth/2.,0,0) aPnt2=Base.Vector(-myWidth/2.,-myThickness/4.,0) aPnt3=Base.Vector(0,-myThickness/2.,0) aPnt4=Base.Vector(myWidth/2.,-myThickness/4.,0) aPnt5=Base.Vector(myWidth/2.,0,0) aArcOfCircle = Part.Arc(aPnt2,aPnt3,aPnt4) aSegment1=Part.Line(aPnt1,aPnt2) aSegment2=Part.Line(aPnt4,aPnt5) aEdge1=aSegment1.toShape aEdge2=aArcOfCircle.toShape aEdge3=aSegment2.toShape aWire=Part.Wire([aEdge1,aEdge2,aEdge3]) aTrsf=Base.Matrix aTrsf.rotateZ(math.pi) # rotate around the z-axis aMirroredWire=aWire.transform(aTrsf) myWireProfile=Part.Wire([aWire,aMirroredWire]) myFaceProfile=Part.Face(myWireProfile) aPrismVec=Base.Vector(0,0,myHeight) myBody=myFaceProfile.extrude(aPrismVec) myBody=myBody.makeFillet(myThickness/12.0,myBody.Edges) neckLocation=Base.Vector(0,0,myHeight) neckNormal=Base.Vector(0,0,1) myNeckRadius = myThickness / 4 myNeckHeight = myHeight / 10 myNeck = Part.makeCylinder(myNeckRadius,myNeckHeight,neckLocation,neckNormal) myBody = myBody.fuse(myNeck) faceToRemove = 0 zMax = -1.0 for xp in myBody.Faces: try: surf = xp.Surface if type(surf) == Part.Plane: z = surf.Position.z               if z > zMax: zMax = z                   faceToRemove = xp        except: continue myBody = myBody.makeThickness([faceToRemove],-myThickness/50, 1.e-3) return myBody

Detaljerad förklaring
import Part, FreeCAD, math from FreeCAD import Base

Vi kommer förstås behöva Del modulen, men också FreeCAD.Base modulen, vilken innehåller grundläggande FreeCAD strukturer som vektorer och matriser.

def makeBottle(myWidth=50.0, myHeight=70.0, myThickness=30.0): aPnt1=Base.Vector(-myWidth/2.,0,0) aPnt2=Base.Vector(-myWidth/2.,-myThickness/4.,0) aPnt3=Base.Vector(0,-myThickness/2.,0) aPnt4=Base.Vector(myWidth/2.,-myThickness/4.,0) aPnt5=Base.Vector(myWidth/2.,0,0)

Här definierar vi vår makeBottle funktion. Denna funktion kan anropas utan argument, som vi gjorde ovan, i vilket fall standardvärden för bredd, höjd, och tjocklek kommer att användas. Sedan så definierar vi ett par punkter som kommer att användas för att bygga vår grundprofil.

aArcOfCircle = Part.Arc(aPnt2,aPnt3,aPnt4) aSegment1=Part.Line(aPnt1,aPnt2) aSegment2=Part.Line(aPnt4,aPnt5)

Här definierar vi själva geometrin: en cirkelbåge, gjord av 3 punkter, och två linjesegment, gjorda av 2 punkter.

aEdge1=aSegment1.toShape aEdge2=aArcOfCircle.toShape aEdge3=aSegment2.toShape aWire=Part.Wire([aEdge1,aEdge2,aEdge3])

Kommer du ihåg skillnaden mellan geometri och former? Här bygger vi former utifrån vår konstruktionsgeometri. 3 kanter (kanter kan vara raka eller krökta), sedan en tråd av dessa tre kanter.

aTrsf=Base.Matrix aTrsf.rotateZ(math.pi) # rotera runt z-axeln aMirroredWire=aWire.transform(aTrsf) myWireProfile=Part.Wire([aWire,aMirroredWire])

Tills nu så har vi bara byggt en halv profil. Lättare än att bygga hela profilen på samma sätt, så behöver vi bara spegla det vi har gjort, och limma ihop båda halvorna. Så vi skapar först en matris. En matris är ett mycket vanligt sätt att tillämpa omvandlingar på objekt i 3D världen, eftersom den i en struktur kan innehålla alla grundläggande omvandlingar som 3D objekt kan påtvingas (flytta, rotera och skala). Här, efter att vi skapat matrisen, så speglar vi den, och vi skapar en kopia av vår tråd med tillämpning av vår omvandlingsmatris. Vi har nu två trådar, och vi kan göra en tredje tråd från dem, eftersom trådar egentligen är listor med kanter.

myFaceProfile=Part.Face(myWireProfile) aPrismVec=Base.Vector(0,0,myHeight) myBody=myFaceProfile.extrude(aPrismVec) myBody=myBody.makeFillet(myThickness/12.0,myBody.Edges)

Nu när vi har en stängd tråd, så kan den omvandlas till en yta. När vi väl har en yta, så kan vi extrudera den. Genom att göra så, så skapar vi en solid. Sedan tillämpar vi en snygg liten fasning på vårt objekt för vi vill ha en bra design, eller hur?

neckLocation=Base.Vector(0,0,myHeight) neckNormal=Base.Vector(0,0,1) myNeckRadius = myThickness / 4. myNeckHeight = myHeight / 10 myNeck = Part.makeCylinder(myNeckRadius,myNeckHeight,neckLocation,neckNormal)

När vår flaskas kropp är skapad, så behöver vi fortfarande skapa en hals. Så vi gör en ny solid, med en cylinder.

myBody = myBody.fuse(myNeck)

Ihopsmältningsoperationen, vilket i andra applikationer ibland kallas för förening, är mycket kraftfull. Den kommer att limma ihop det som behövs, och ta bort de delar som inte behövs.

return myBody

Sedan så får vi tillbaka vår Del solid som ett resultat av vår funktion. Denna Del solid, liksom andra Del former, kan tillskrivas ett objekt i ett FreeCAD dokument, med:

myObject = FreeCAD.ActiveDocument.addObject("Part::Feature","myObject") myObject.Shape = bottle

eller, mer enkelt:

Part.show(bottle)

Ladda och spara
Det finns flera sätt att spara ditt arbetet i Del modulen. Du kan förstås spara ditt FreeCAD dokument, men du kan också spara Del objekt direkt till vanliga CAD format, som BREP, IGS, STEP och STL.

Att spara en form till en fil är lätt. det finns exportBrep, exportIges, exportStl och exportStep metoder tillgängliga för alla form objekt. Så genom att göra:

import Part s = Part.makeBox(0,0,0,10,10,10) s.exportStep("test.stp")

detta kommer att spara vår låda i en STEP fil. För att ladda en BREP, IGES eller STEP fil, gör bara motsatsen:

import Part s = Part.Shape s.read("test.stp")

Notera att import eller öppning av BREP, IGES eller STEP filer även kan göras direkt via Fil -> Öppna eller Fil -> Importera menyn. För närvarande är export fortfarande inte möjligt den vägen, men ska vara det snart.