Programujeme: Vytvoření reálného stehu v modelu
Publikováno: 20. září 2010 | Zobrazeno: 5860x
Tento článek se váže k tématu Kopírování objektu podél křivky (viz http://www.catia-forum.cz/forum/topic.php?topic_id=176). Uživatel se v něm ptal na možnost vytvoření opakované geometrie, která by se řídila obecnou křivkou ležící v obecné ploše. Konkrétně se jednalo o "vyšití" švu (stehu) na látce, které by se co nejvíce podobalo skutečnosti. V diskusi se psalo o několika možnostech. Jednou z nich bylo použití Law editoru, kde se pomocí fce Sweep (s referenční plochou) vytvořila plocha, jejíž jedna hranice se periodicky vynořovala a znovu zanořovala do pomyslné látky (ref. plochy), a po této hranici se protáhl druhý kruhový Sweep - vlastní nit. Řešení velice efektivní a navíc plně parametrické (změna tvaru látky a průběh švu se ihned promítlo do výsledného švu), ale výsledek se skutečnému tvaru příliš nepodobal. Mne napadlo zkusit tento problém vyřešit makrem a rád bych tu dnes celé řešení uveřejnil.
Začátek o konec stehu je vytvořen jako Blend, kdy jsou spojeny dva kruhové profily a jeden z profilů je tangentně napojen na již vytvořený Sweep. Bylo tedy třeba nadefinovat tyto dva (čtyři) profily. První z nich, ten menší, je vytvořen funkcí Circle (bod, rovina kolmá na řídící křivku procházející tímto bodem jako support a rádius). Druhý profil by se dal normálně vzít z hraniční křivky Sweepu, ale podstrčit makru tuto křivku (což je Brep element) je skoro nemožné. Takže jsem druhý profil vytvořil jako průsečík další roviny a Sweepu - opět se vytvořila kružnice.
Teď už jen zbývá popsat, jak se vytvořily body, ve kterých jsou tyto roviny a které zároveň určují limity (délku) Sweepu.
Jak jsem již psal, vstupem pro steh je jedna křivka ležící na ploše. My na této křivce musíme nejdříve nadefinovat vždy čtyři body, které určují právě jeden steh:
Poslední částí článku je kompletní výpis zdrojového kódu v CATScriptu.
Poznámka:
Makro bylo testováno na V5 R19 SP3. Pro správný běh je požadována licence HD2 (MD2 + GSD). Rychlost šití stehu závisí na vstupních parametrech a není možné jako vstup použít spojitou křivku.
Popis geometrie
Požadavek na tvar stehu byl popsán jako "váleček", který má šté konce, tedy něco jako je na obrázku. Celý steh by měl ležet vně látky a konce by se do ní měly zanořovat (nebo alespoň nevyčnívat). První problém tedy byl vymyslet, pomocí kterých funkcí se geometrie vytvoří. Pokud totiž používame v makru funkci, u které je třeba při její definici vybírat i směry a orientace (je více možností, jak se plocha vytvoří), nikdy dopředu nevíme, kterou možnosti si makro vybere. Takže jsem se snažil použít co možná nejjednodušší funkce. Pro středovou část stehu jsem zvolil Sweep s kruhovým profilem, definovaný limitní křivkou a tangentní plochou (úhly 0 a 360°). Už i tady jsou ale dvě možnosti, jak se může Sweep vytvořit - nad nebo pod plochou (látkou). V tomto příkladu jsem možnost uživatele zvolit si orientaci nijak neřešil. Sweep se vytvoří na té straně, kam směřuje normála - to lze dopředu zkontrolovat.Začátek o konec stehu je vytvořen jako Blend, kdy jsou spojeny dva kruhové profily a jeden z profilů je tangentně napojen na již vytvořený Sweep. Bylo tedy třeba nadefinovat tyto dva (čtyři) profily. První z nich, ten menší, je vytvořen funkcí Circle (bod, rovina kolmá na řídící křivku procházející tímto bodem jako support a rádius). Druhý profil by se dal normálně vzít z hraniční křivky Sweepu, ale podstrčit makru tuto křivku (což je Brep element) je skoro nemožné. Takže jsem druhý profil vytvořil jako průsečík další roviny a Sweepu - opět se vytvořila kružnice.
Teď už jen zbývá popsat, jak se vytvořily body, ve kterých jsou tyto roviny a které zároveň určují limity (délku) Sweepu.
Jak jsem již psal, vstupem pro steh je jedna křivka ležící na ploše. My na této křivce musíme nejdříve nadefinovat vždy čtyři body, které určují právě jeden steh:
- 1. bod - počáteční malý profil prvního Blendu (Circle)
- 2. bod - počátek Sweepu (1. limit), rovina (support) pro druhý profil prvního Blendu
- 3. bod - konec Sweepu (2. limit), rovina (support) pro první profil druhého Blendu
- 4. bod - koncový profil druhého Blendu (Circle)
Určení počtu vytvořených stehů
Vzdálenosti jednotlivých bodů se počítají z uživatelem zadaných hodnot na počátku běhu makra. Každý další počáteční bod stehu se pak vytvoří ve vzdálenosti součtu všech dílčích vzdáleností (délka Sweepu, délka Blendů, rozteč stehů). Abychom stehy nedělali donekonečna, změříme si na začátku křivku a počítáme vzdálenost od počátku křivky, ve které je nově vytvářený bod. Jakmile se dostaneme na konec křivky, ukončíme smyčku pro tvorbu jednotlivého stehu, spojíme všechny tři plochy do Joinu a ten vložíme jako jednu mrtvou plochu do předem připraveného geometrického setu, obarvíme ji a přesuneme do nějaké hladiny. Nakonec vybereme všechnu pomocnou geometrii (body, roviny, profily) a smažeme je. Stehy tedy nejsou parametrické, ale pokud by se vynechala část kódu s "umrtvením" a smazáním pomocné geometrie, samozřejmě by parametrické byly. Pak by ale model poměrně hodně datově narostl, proto se mi tato možnost zdá být výhodnější.Možné chyby
Při běhu makra může nastat několik chyb. Nejpravděpodobnější z nich bude případ, kdy se některá z ploch nevytvoří v důsledku "složitosti" vstupu, tj. Sweep nebo Blend se překroutí. V tu chvíli makro skončí a steh se nevyšije celý. Další chybou může být to, že se steh začne tvořit na druhé straně, než bychom potřebovali. Pokud ale víme, že se steh vytvoří na straně normály plochy (látky), můžeme si normálu předem otočit.Videoukázka
Na závěr se můžete ve videoukázce podívat, jak makro "šije" v praxi. Pokusil jsem se namodelovat dva kusy látky, které budeme sešívat dvěma paralelními stehy. Pro větší názornost je každý steh vyšitý s jinými parametry.Poslední částí článku je kompletní výpis zdrojového kódu v CATScriptu.
Poznámka:
Makro bylo testováno na V5 R19 SP3. Pro správný běh je požadována licence HD2 (MD2 + GSD). Rychlost šití stehu závisí na vstupních parametrech a není možné jako vstup použít spojitou křivku.
Zdrojový kód
Dim oPart As Part
Dim oHB As HybridBody
Dim oHSF As HybridShapeFactory
Dim oRefCurve, oRefStartPoint As Reference
Dim oSPAWB As SPAWorkbench
Dim oMeasurable As Measurable
Dim StichLength, Pitch, StartEnd, YarnDiam, CurveLength, TotalDistance As Double
Sub CATMain()
Set oActiveDocument = CATIA.ActiveDocument
Set oSelection = oActiveDocument.Selection
Set oPart = oActiveDocument.Part
Dim Filter(0)
Filter(0) = "MonoDim"
Status = oSelection.SelectElement2(Filter, "Vyberte osu stehu...", False)
If Status = "Cancel" Then
Exit Sub
End If
Set oRefCurve = oPart.CreateReferenceFromObject(oSelection.Item(1).Value)
oSelection.Clear()
Filter(0) = "BiDim"
Status = oSelection.SelectElement2(Filter, "Vyberte podkladovou plochu stehu...", alse)
If Status = "Cancel" Then
Exit Sub
End If
Set oRefSurface = oPart.CreateReferenceFromObject(oSelection.Item(1).Value)
oSelection.Clear()
'zadani vstupnich hodnot
StichLength = CSng(InputBox("Zadejte delku stehu", "Delka", "10"))
StartEnd = CSng(InputBox("Zadejte delku pocatku/konce stehu...", "Pocatek/Konec", 3))
Pitch = CSng(InputBox("Zadejte vzdalenost mezi stehy...", "Roztec", "0,5"))
YarnDiam = CSng(InputBox("Zadejte prumer nite...", "Nit", "0,5"))
' vytvorime set
Set oHB = oPart.HybridBodies.Add()
oHB.Name = "Stehy"
Set oHSF = oPart.HybridShapeFactory
Set oPoint = oHSF.AddNewPointOnCurveFromPercent(oRefCurve, 0, True)
oHB.AppendHybridShape(oPoint)
oPart.Update()
'zmerime delku krivky
Set oSPAWB = oActiveDocument.GetWorkbench("SPAWorkbench")
Set oMeasurable = oSPAWB.GetMeasurable(oRefCurve)
TotalDistance = 0
CurveLength = oMeasurable.Length
Set oRefStartPoint = oPart.CreateReferenceFromObject(oPoint)
'smycka pro vysiti vsech stehu
Do Until TotalDistance > CurveLength - StichLength
' 1. krok - pocatecni profil
Set oStartPoint = oHSF.AddNewPointOnCurveWithReferenceFromDistance(oRefCurve, oRefStartPoint, TotalDistance + Pitch, 1)
oHB.AppendHybridShape(oStartPoint)
Set oRefPoint = oPart.CreateReferenceFromObject(oStartPoint)
Set oStartPlane = oHSF.AddNewPlaneNormal(oRefCurve, oRefPoint)
oHB.AppendHybridShape(oStartPlane)
Set oRefSupport = oPart.CreateReferenceFromObject(oStartPlane)
Set oStartProfile = oHSF.AddNewCircleCtrRad(oRefPoint, oRefSupport, True, 0.02)
oHB.AppendHybridShape(oStartProfile)
oPart.Update()
' 2/1. krok - sweep
Set oFullThickStartPoint = oHSF.AddNewPointOnCurveWithReferenceFromDistance(oRefCurve, oRefStartPoint,TotalDistance + Pitch + StartEnd, 1)
Set oFullThickEndPoint = oHSF.AddNewPointOnCurveWithReferenceFromDistance(oRefCurve, oRefStartPoint, TotalDistance + Pitch + StichLength - StartEnd , 1)
oHB.AppendHybridShape(oFullThickStartPoint)
oHB.AppendHybridShape(oFullThickEndPoint)
Set oRefPoint1 = oPart.CreateReferenceFromObject(oFullThickStartPoint)
Set oRefPoint2 = oPart.CreateReferenceFromObject(oFullThickEndPoint)
Set oSweep = oHSF.AddNewSweepCircle(oRefCurve)
oSweep.Mode = 9
oSweep.Reference = oRefSurface
oSweep.SetRadius 1, YarnDiam
oSweep.SetAngle 1, 0
oSweep.SetAngle 2, 360
oSweep.SetRelimiters oRefPoint1, 0, oRefPoint2, 1
oHB.AppendHybridShape(oSweep)
oPart.Update()
'krok 2/2. - pocatek a konec sweepu
Set oRefPoint = oPart.CreateReferenceFromObject(oFullThickStartPoint)
Set oFullThickStartPlane = oHSF.AddNewPlaneNormal(oRefCurve, oRefPoint)
oHB.AppendHybridShape(oFullThickStartPlane)
Set oRefPoint = oPart.CreateReferenceFromObject(oFullThickEndPoint)
Set oFullThickEndPlane = oHSF.AddNewPlaneNormal(oRefCurve, oRefPoint)
oHB.AppendHybridShape(oFullThickEndPlane)
oPart.Update()
Set oRef1 = oPart.CreateReferenceFromObject(oSweep)
Set oRef2 = oPart.CreateReferenceFromObject(oFullThickStartPlane)
Set oRef3 = oPart.CreateReferenceFromObject(oFullThickEndPlane)
Set oFullThickStartProfile = oHSF.AddNewIntersection(oRef1, oRef2)
oHB.AppendHybridShape(oFullThickStartProfile)
Set oFullThickEndProfile = oHSF.AddNewIntersection(oRef1, oRef3)
oHB.AppendHybridShape(oFullThickEndProfile)
oPart.Update()
'3. krok - koncovy profil
Set oEndPoint = oHSF.AddNewPointOnCurveWithReferenceFromDistance(oRefCurve, oRefStartPoint, TotalDistance + Pitch + StichLength, 1)
oHB.AppendHybridShape(oEndPoint)
Set oRefPoint = oPart.CreateReferenceFromObject(oEndPoint)
Set oEndPlane = oHSF.AddNewPlaneNormal(oRefCurve, oRefPoint)
oHB.AppendHybridShape(oEndPlane)
Set oRefSupport = oPart.CreateReferenceFromObject(oEndPlane)
Set oEndProfile = oHSF.AddNewCircleCtrRad(oRefPoint, oRefSupport, True, 0.02)
oHB.AppendHybridShape(oEndProfile)
oPart.Update()
'4. krok - spojeni profilu
Set oRefCurve1 = oPart.CreateReferenceFromObject(oFullThickStartProfile)
Set oRefCurve2 = oPart.CreateReferenceFromObject(oStartProfile)
Set oRefSupport = oPart.CreateReferenceFromObject(oSweep)
Set oBlend1 = oHSF.AddNewBlend()
oBlend1.SetCurve 1, oRefCurve1
oBlend1.SetCurve 2, oRefCurve2
oBlend1.SetSupport 1, oRefSupport
oBlend1.SetContinuity 1, 1
oBlend1.SetOrientation 1, 1
oBlend1.Coupling = 1
oBlend1.SetTransition 1, -1
oBlend1.SetTrimSupport 1, 1
oBlend1.SetBorderMode 1, 1
oHB.AppendHybridShape(oBlend1)
Set oRefCurve1 = oPart.CreateReferenceFromObject(oFullThickEndProfile)
Set oRefCurve2 = oPart.CreateReferenceFromObject(oEndProfile)
Set oBlend2 = oHSF.AddNewBlend()
oBlend2.SetCurve 1, oRefCurve1
oBlend2.SetCurve 2, oRefCurve2
oBlend2.SetSupport 1, oRefSupport
oBlend2.SetContinuity 1, 1
oBlend2.SetOrientation 1, 1
oBlend2.Coupling = 1
oBlend2.SetTransition 1, 1
oBlend2.SetTrimSupport 1, 1
oBlend2.SetBorderMode 1, 1
oHB.AppendHybridShape(oBlend2)
oPart.Update()
Set oRef1 = oPart.CreateReferenceFromObject(oBlend1)
Set oRef2 = oPart.CreateReferenceFromObject(oBlend2)
Set oJoin = oHSF.AddNewJoin(oRefSupport, Nothing)
oJoin.AddElement(oRef1)
oJoin.AddElement(oRef2)
oJoin.SetConnex(0)
oJoin.SetManifold(1)
oJoin.SetSimplify(0)
oJoin.SetSuppressMode(0)
oJoin.SetDeviation(0.1)
oJoin.SetAngularToleranceMode(0)
oJoin.SetAngularTolerance(0.5)
oJoin.SetFederationPropagation(0)
oHB.AppendHybridShape(oJoin)
oPart.Update()
'vytvoreni mrtve plochy
Set oRefDatum = oPart.CreateReferenceFromObject(oJoin)
Set oDatum = oHSF.AddNewSurfaceDatum(oRefDatum)
oHB.AppendHybridShape(oDatum)
oHSF.DeleteObjectForDatum(oRefDatum)
'vlozime mrtvou plochu Do modelu a presuneme ji Do hladiny 999
oSelection.Add(oDatum)
oSelection.VisProperties.SetLayer catVisLayerBasic, 999
oSelection.Clear()
oPart.Update()
' smazani docasnych elementu
oSelection.Add(oHB)
oSelection.Search(". - Layer=999, sel")
oSelection.Delete()
'celkova delka stehu
TotalDistance = TotalDistance + StichLength + Pitch
Loop
End Sub