| | | Gut zu wissen: Hilfreiche Tipps und Tricks aus der Praxis prägnant, und auf den Punkt gebracht für Autodesk Produkte |
Autor
|
Thema: Curve.extend, Curve.getsplitCurves Abflüge (2475 mal gelesen)
|
Christian Blei Mitglied
Beiträge: 124 Registriert: 23.06.2008 Thinkpad W520, 16GB Win 7,Autocad 2012, ProStructures V8i4+5 , VBA, VB.NET,
|
erstellt am: 02. Nov. 2009 10:51 <-- editieren / zitieren --> Unities abgeben:
Hallo! Ich habe Kurven und Punkte in Selectionsets. Jeder Punkt liegt auf einem "Querschnitt" einer Kurve und ist dieser über EEDs zugeordnet. Jede Kurve möchte ich über .GetSplitCurves mit .GetClosestPoint und .GetDistanceatPoint an den Aussenpunkten trimmen bzw. falls die ClosestPoints die Kurve Start oder Endpunkte sind über .GetClosestPoint, extend=true und Curve.Extend die Kurve bis zu diesen ClosestPoints verlängern. Soweit so gut. Das funktioniert auch Alles bis zu curve. extend und curve.getsplitcurves, da bekomme ich exceptions mit der Meldung "eInvalidInput". Was mache ich falsch? Mein Code: Imports Autodesk.AutoCAD Public Class NovStrct01_PrimeGeo
Public Shared Sub createPrimeGeo() Dim Ed As EditorInput.Editor = ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
Dim TAcadDoc As ApplicationServices.Document = Nothing Dim TAcadDocLock As ApplicationServices.DocumentLock = Nothing Dim tTrAct As DatabaseServices.Transaction = Nothing Dim tCurves() As DatabaseServices.Curve = {} Dim tDBPoints() As DatabaseServices.DBPoint = {} Try TAcadDoc = ApplicationServices.Application.DocumentManager.MdiActiveDocument TAcadDocLock = TAcadDoc.LockDocument tTrAct = TAcadDoc.TransactionManager.StartTransaction '' Open the Block table for read
Dim tModSP As DatabaseServices.BlockTableRecord = BLEI.AcadLib.getModelspace(TAcadDoc.Database, tTrAct, DatabaseServices.OpenMode.ForWrite) '' get Syslines
Dim tRes As EditorInput.PromptSelectionResult = TAcadDoc.Editor.SelectAll If (tRes IsNot Nothing) AndAlso (tRes.Status = EditorInput.PromptStatus.OK) AndAlso (tRes.Value.Count > 0) Then For Each tObjId As DatabaseServices.ObjectId In tRes.Value.GetObjectIds If (tObjId.IsValid) AndAlso Not (tObjId.IsErased) Then Dim tDBObj As DatabaseServices.DBObject = tTrAct.GetObject(tObjId, DatabaseServices.OpenMode.ForRead, True) Dim tEntity As DatabaseServices.Entity = CType(tDBObj, DatabaseServices.Entity) If (tEntity.Layer = "AFP_PrimelineChildSystem") Then If (TypeOf tEntity Is DatabaseServices.Curve) Then ReDim Preserve tCurves(tCurves.GetUpperBound(0) + 1) tCurves(tCurves.GetUpperBound(0)) = CType(tEntity, DatabaseServices.Curve) End If End If End If Next End If ''get all SysLinepoints
Dim tFilterValues(2) As DatabaseServices.TypedValue tFilterValues(0) = New DatabaseServices.TypedValue(0, "POINT") tFilterValues(1) = New DatabaseServices.TypedValue(8, "AFP_PrimelineChildSystemPoint") tFilterValues(2) = New DatabaseServices.TypedValue(1001, "SysPoint") Dim tFilter As EditorInput.SelectionFilter = New EditorInput.SelectionFilter(tFilterValues) Dim tDBPointSel As EditorInput.PromptSelectionResult = TAcadDoc.Editor.SelectAll(tFilter) If (tDBPointSel IsNot Nothing) AndAlso (tDBPointSel.Status = EditorInput.PromptStatus.OK) AndAlso (tDBPointSel.Value.Count > 0) Then For Each tObjId As DatabaseServices.ObjectId In tDBPointSel.Value.GetObjectIds If (tObjId.IsValid) AndAlso Not (tObjId.IsErased) Then Dim tDBObj As DatabaseServices.DBObject = tTrAct.GetObject(tObjId, DatabaseServices.OpenMode.ForRead, True) Dim tDBPoint As DatabaseServices.DBPoint = CType(tDBObj, DatabaseServices.DBPoint) ReDim Preserve tDBPoints(tDBPoints.GetUpperBound(0) + 1) tDBPoints(tDBPoints.GetUpperBound(0)) = tDBPoint End If Next End If Dim tCurve As DatabaseServices.Curve = Nothing For Each tCurve In tCurves tCurve = CType(tTrAct.GetObject(tCurve.ObjectId, DatabaseServices.OpenMode.ForWrite, False, False), DatabaseServices.Curve) 'Get related points with point eed Dim tSysDbPoint() As DatabaseServices.DBPoint = {} Dim tDBPoint As DatabaseServices.DBPoint = Nothing For Each tDBPoint In tDBPoints Dim tXDataValues() As DatabaseServices.TypedValue = tDBPoint.GetXDataForApplication("SysPoint").AsArray If Not tXDataValues Is Nothing Then Dim tValue As String = CType(tXDataValues(1).Value, String) If tCurve.Handle.ToString = tValue Then ReDim Preserve tSysDbPoint(tSysDbPoint.GetUpperBound(0) + 1) tSysDbPoint(tSysDbPoint.GetUpperBound(0)) = CType(tDBPoint, DatabaseServices.DBPoint) End If End If Next
'get closest Points
Dim tExtend As Boolean = False Dim tPoints3d() As Geometry.Point3d = {} Dim tDists() As Double = {} Dim tPoint3dCl As Geometry.Point3d = New Geometry.Point3d For Each tDBPoint In tSysDbPoint
Dim tPoint3d As Geometry.Point3d = New Geometry.Point3d tPoint3d = tDBPoint.Position tPoint3dCl = tCurve.GetClosestPointTo(tPoint3d, tExtend) ' Check if tpointCl is equal tcurve.start or Endpoint then use extend Dim tCheckPoint3d As Geometry.Point3d = New Geometry.Point3d tCheckPoint3d = tCurve.StartPoint If tPoint3dCl.Equals(tCheckPoint3d) Then tExtend = True tPoint3dCl = tCurve.GetClosestPointTo(tPoint3d, tExtend) Dim tExtendStart As Boolean = False
‘Abflug bei tCurve.Extend tCurve.Extend(tExtendStart, tPoint3dCl) End If tCheckPoint3d = tCurve.EndPoint If tPoint3dCl.Equals(tCheckPoint3d) Then tExtend = True tPoint3dCl = tCurve.GetClosestPointTo(tPoint3d, tExtend) ‘Abflug bei tCurve.Extend tCurve.Extend(False, tPoint3dCl) End If ReDim Preserve tPoints3d(tPoints3d.GetUpperBound(0) + 1) tPoints3d(tPoints3d.GetUpperBound(0)) = CType(tPoint3dCl, Geometry.Point3d) Dim tDist As Double = tCurve.GetDistAtPoint(tPoint3dCl) ReDim Preserve tDists(tDists.GetUpperBound(0) + 1) tDists(tDists.GetUpperBound(0)) = tDist Next
Array.Sort(tDists, tPoints3d) Dim tPoints3dColl As Geometry.Point3dCollection = New Geometry.Point3dCollection Dim I As Integer = 0 For Each tPoint3dCl In tPoints3d tPoints3dColl.Add(tPoint3dCl) Next Dim tCurvesCol As DatabaseServices.DBObjectCollection = New DatabaseServices.DBObjectCollection ‘Abflug bei getsplitcurves tCurvesCol = tCurve.GetSplitCurves(tPoints3dColl)
Dim pCurve As DatabaseServices.Curve = Nothing For Each pCurve In tCurvesCol Next Next
tTrAct.Commit() Catch ex As Exception Call MsgBox("Unbekannter Fehler: " & ex.Message) Finally If tTrAct IsNot Nothing Then tTrAct.Dispose() If TAcadDocLock IsNot Nothing Then TAcadDocLock.Dispose() End Try End Sub End Class
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Ex-Mitglied
|
erstellt am: 02. Nov. 2009 14:58 <-- editieren / zitieren -->
Hi Christian, (mit den Zeichnungen aus PM): Punkt 1 ==> tCurve.GetSplitCurves(tPoints3dColl) Dazu Auszug aus der Dokumentation (arxdoc.chm) ...it is possible that the function might return an ErrorStatus other than Acad::eOk and still have appended some pointers to subcurves to the curveSegments array (AcDbArc does this)... Dazu noch meine Meinung dazu: Nicht für alle Objekttypen, die sich auf DatabaseServices.Curve casten lassen, funktioniert diese Methode fehlerfrei. Abhängig von dem Anwendungsfall (und auch von der AutoCAD-Version) habe ich mir z.T. damit beholfen, dass ich die Curve herangezogen habe, aus dieser (mittels segmentieren der Curve in kleine, gerade Segmente) eine 3D-Poly erzeugt habe und diese dann weiterverarbeitet habe. Es könnte jetzt noch möglich sein, da es das Splitten von Curves auch für Curves der Assembly 'Autodesk.AutoCAD.Geometry' gibt, dass man damit weiterkommt. Leider lassen sich aber die DatabaseServices.Curves nicht einfach in Geometry.Curves2D oder Geometry.Curves.3D casten, diese müssen neu erstellt werden, damit hab ich mich aber bisher noch nicht auseinandergesetzt. Lass mal wissen, ob das Segmentieren für Deinen Anwendungsfall eine mögliche Methode wäre. Punkt 2 ==> tCurve.Extend(tExtendStart, tPoint3dCl)
Da passiert eigentlich nichts anderes, als dass der Startpunkt/Endpunkt verändert wird, hast Du schon versucht (ich hab's jetzt nicht, weil ich keinen Fall finde) einfach den Startpunkt/Endpunkt direkt zu verändern? ==> Jedenfalls aber Vorsicht (in jedem Fall, egal ob x.Extend oder direkt ändern): Bögen ändern damit ihren Radius! - alfred -
------------------ www.hollaus.at |
Christian Blei Mitglied
Beiträge: 124 Registriert: 23.06.2008 Thinkpad W520, 16GB Win 7,Autocad 2012, ProStructures V8i4+5 , VBA, VB.NET,
|
erstellt am: 02. Nov. 2009 20:57 <-- editieren / zitieren --> Unities abgeben:
Hallo Alfred, schade..... Ich habe etwas rumprobiert. Getsplitcurves funtioniert bei mir nur bei Lines und Polylines ( mit bulges>0), aber interessanterweise nicht bei arcs. Extend hat nach der arxdoc die Rückgabe system.void..... Dein Typ startpoint, endpoint zu setzen funtioniert nur bei Line..... Interessanterweise ist auch bei den Autodesk Diskussion groups nichts über derlei Probleme zu lesen. Das es Fälle gibt in denen .GetSplitLines nicht funktioniert. Ich werde mir jetzt noch die Geometry Curves anschauen und dann überlegen, was ich mache. Dein Vorschlag zu segmentieren: Ich will ja mit dieser Curve als Leitline noch Solids loften. Muss ich mir ansschauen, was da rauskommt. Wo genau in der ArxDoc.chm steht denn, dass .GetSplitCurves nicht immer eine Rückgabe hat? Ich finde die Stelle, die du zitierst nicht..... Ich finde nur sowas: GetSplitCurves Autodesk.AutoCAD.DatabaseServices.DBObjectCollection GetSplitCurves( Autodesk.AutoCAD.Geometry.DoubleCollection value) Parameters value Input Autodesk.AutoCAD.Geometry.DoubleCollection object. Return Type Autodesk.AutoCAD.DatabaseServices.DBObjectCollection Aber danke für deine Antwort! Grüsse, Christian
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Ex-Mitglied
|
erstellt am: 02. Nov. 2009 21:22 <-- editieren / zitieren -->
Hi, >> Getsplitcurves ... aber interessanterweise nicht bei arcs Mein Ansatz wäre in diesem Fall: die Funktion mal starten in einem Try..Catch..End Try, fliegt diese ab und landet im Catch, dann hätte ich versucht, aus dem Basiselement eine Polylinie abzuleiten und diese nochmals in das getSplittedCurves hineinzuschicken, im schlimmsten Fall mit der Variante der Segmentierung. >> Interessanterweise ist auch bei den Autodesk Diskussion groups nichts über derlei Probleme zu lesen
Ich hab jetzt nicht danach gesucht, aber meine Einschätzung in diesem Fall wäre, dass 90% derer, die dort Beiträge plazieren, überhaupt nicht bis hierher kommen. Ich möchte jetzt den 90% mit dieser Bemerkung weh tun, die brauchen einfach nicht solch eine Tiefe. >> Wo genau in der ArxDoc.chm steht denn
Gesucht hätte ich zwar in 2010, es steht aber auch in der 2009-doc, zu finden unter:
AcDb Classes > AcDbCurve Class > AcDbCurve Methods > getSplitCurves Method > AcDbCurve::getSplitCurves Method (const AcGePoint3dArray&, AcDbVoidPtrArray&) - alfred - ------------------ www.hollaus.at |
Christian Blei Mitglied
Beiträge: 124 Registriert: 23.06.2008 Thinkpad W520, 16GB Win 7,Autocad 2012, ProStructures V8i4+5 , VBA, VB.NET,
|
erstellt am: 02. Nov. 2009 21:50 <-- editieren / zitieren --> Unities abgeben:
Alfred, Vielen Dank. An die Umwandlung der Arcs in Polylines habe ich auch gedacht. Aber mein Grundmakro lässt alle offenen ebenen Kurven zu. Line, Polyline, arc, ellipse(arc), Spline. Also vielleicht doch segmentieren..... Danke auch für den Hilfepfad. Gruss, Christian Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Christian Blei Mitglied
Beiträge: 124 Registriert: 23.06.2008 Thinkpad W520, 16GB Win 7,Autocad 2012, ProStructures V8i4+5 , VBA, VB.NET,
|
erstellt am: 10. Nov. 2009 09:47 <-- editieren / zitieren --> Unities abgeben:
Alfred, ich habe mich jetzt doch gegen das Segmentieren entschieden. Die .Geometry habe ich auch angeschaut. Ein Witz ist natürlich, dass man die .Databaseservices Entities nachbauen muss. Ich habe ein nettes Zitat von Tony Tanzillo gefunden, dass sich auf Solids bezieht, aber auch hierzu passt: In the case of solids that retain the entities used to define them, those entities are stored in the solid's definition as ACIS objects. Even if you took the standard approach/kludge of recreating the object from scratch (which is often done with composite solids created from boolean operations), there is still the problem of not having the original defining entities in a usable form. The API support for 3D in AutoCAD is bare-minimal, or in practicle times, nearly useless. It seems to be carefully designed to prevent it from being used to create solutions that are competitive with other Autodesk products, like Inventor. Ich habe mir angeschaut, was bei .GetSplitCurves passiert und festgestellt, dass die Abflüge daher kommen, dass .GetSplitCurves nicht alle Punkte annimmt, die man mit .GetClosestPointTo bekommt. Übergibt man einen Parameterarray, funzt .GetSplitCurves immer. Also habe ich halt iterativ Paramter gesucht, die den ClosestPoints entsprechen, wenn ich bei .GetParamterFrom(Point) eine Abbflug habe.
Apropos Parameter: Spannend
Bei Lines: Anfangspunkt:0 Endpunkt: Länge der Linie dazwischen . relative Länge Paramter für Punkte ausserhalb, für Curve.extend: Da ist die Länge 1 und man ginbt einhe Faktor von 1 an. Bei Arcs zum Beispiel: Anfangspunkt: Anfanswinkel Endpunkt: Endwinkel Ausserhalb. entsprechender Anfangs, bzw. Endwinkel Polylinien: Anfangspunkt: 0 Endpunkt: integer, der Anzahl der Vertices angibt. Innerhalb: relative Länge bis Punkt Ausserhalb: Faktor der Anzahl der Vertices Darauf muss man erstmal kommen, da ist im Netz auch nichts zu finden. Nachdem ich jetzt .GetSplitCurves benutze um Kurven zu kürzen, hatte ich noch das Problem, dass ich in anderen Entites den Handle der jeweiligen Urspungskurve mit XData angehängt habe. Neue Kurve, neuer Handle. Ich habe jetz die XDatA mit Entity.XData(resultBuffer) überschrieben. Meine Fragen hierzu: 1. Handles Lassen sich nciht editieren, da geht gar nichts, oder? Da ich ja die Ursprungskurve lösche, könnte ich ja ihrten Handle verwenden. 2. In VBA habe ich die Möglichkeit eine Value eines XDataeintrages zu editieren, indem ich den Eintrag über seine Index ansteuere. Kann ich sowas beim definiern desw ResultBuffers auch machen, oder muss ich, wie ich es getan habe, die XData komplett neu machen, wie ich es getan habe: Code: Dim tResBuf As DatabaseServices.ResultBuffer = NewDatabaseServices.ResultBuffer tResBuf.Add(New DatabaseServices.TypedValue(1001, "SysPoint")) tResBuf.Add(New DatabaseServices.TypedValue(1000, tXDataValues(1).Value)) tResBuf.Add(New DatabaseServices.TypedValue(1000, pCurve.Handle.ToString)) tDBPoint.XData = tResBuf tResBuf = Nothing tXDataValues(1).Value)) ändert sich hierbei nicht. Den Wert lese ich aus mit: tDBPoint.UpgradeOpen() tXDataValues = tDBPoint.GetXDataForApplication("SysPoint").AsArray If Not tXDataValues Is Nothing Then Dim tValue As String = CType(tXDataValues(1).Value, String) und dann halt gleich wieder ein. Das würde ich mir natürlich gerne sparen, wenn es geht. Jetzt gehe ich daran, Querschnitte an den getrimmten Kurven zu loften. Das wird wieder ein kleines Abenteuer werden. Extruden geht nicht, da die Querschnitte immer senkrecht zur den Kurven stehen müssen. Gruss Christian Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Ex-Mitglied
|
erstellt am: 10. Nov. 2009 10:08 <-- editieren / zitieren -->
Hi Christian, >> Handles Lassen sich nciht editieren, da geht gar nichts, oder? Doch, da geht schon was. Du kannst den Handle eines bestehenden Elements an ein anderes übergeben, wenn das bestehende Element gelöscht wird. Ich sitz jetzt nicht am richtigen Rechner, rein aus dem Gedächtnis heraus such mal nach 'HandOverTo' (kann aber leider auch anders benannt sein, eben Alzheimer). >> XDataeintrages zu editieren, indem ich den Eintrag über seine Index ansteuere
ResultBuffer ist byValue, damit kannst Du nur vom Element in den Speicher einlesen, im Speicher den Array behandeln und dann den gesamten Satz wieder ans Element anhängen. Tony's Aussagen kommen oft sehr gekonnt zynisch in Richtung Autodesk, er ist gut, aber ich könnte mir auch vorstellen, für Autodesk ziemlich unangenehm.
Gratuliere zur Lösung mit SplittedCurves. - alfred - ------------------ www.hollaus.at |
Christian Blei Mitglied
Beiträge: 124 Registriert: 23.06.2008 Thinkpad W520, 16GB Win 7,Autocad 2012, ProStructures V8i4+5 , VBA, VB.NET,
|
erstellt am: 10. Nov. 2009 10:22 <-- editieren / zitieren --> Unities abgeben:
Alfred, Du antwortest ja schnell! ich werde gleich mal machdem HandOverTo fanden. Und versuche mich auch am editieren des XDataArrays. Tony vergisst auch manchmal, dass Anfänger sich in den Foren verirren oder halt von Tuten und Blasen keine Ahnung haben und gibt Ihnen eines auf die Mütze. Das finde ich dann etwas daneben. Autocad kann er schon attackieren...... Gruss Christian
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Christian Blei Mitglied
Beiträge: 124 Registriert: 23.06.2008 Thinkpad W520, 16GB Win 7,Autocad 2012, ProStructures V8i4+5 , VBA, VB.NET,
|
erstellt am: 10. Nov. 2009 14:01 <-- editieren / zitieren --> Unities abgeben:
Hi Alfred, ich habe mir .HandOverTo mal in der ARXDbReferenz durchgelesen und dann versucht es einzubauen. Code:
Try Array.Sort(tParams) Dim tDoubleCol As Geometry.DoubleCollection = New Geometry.DoubleCollection tDoubleCol.Add(tParams(0)) tDoubleCol.Add(tParams(tParams.Length - 1)) Dim tCurvesCol As DatabaseServices.DBObjectCollection = New Databaservices.DBObjectCollection
Try tCurvesCol = tCurve.GetSplitCurves(tDoubleCol) Dim pCurve As DatabaseServices.Curve = Nothing If tCurvesCol.Count = 3 Then tCurvesCol(0).Dispose() pCurve = CType(tCurvesCol(1), DatabaseServices.Curve) tCurvesCol(2).Dispose() tModSP.UpgradeOpen() tCurve.HandOverTo(pCurve, True, False) tCurve.Erase() tModSP.AppendEntity(pCurve) tTrAct.AddNewlyCreatedDBObject(pCurve, True) etc. Ich bekomme aber bei tCurve.HandOverTo(pCurve, True, False) die fehlermeldung:
eInvalidContext obwohl tCurve WriteEnabled ist und pCurve not TransactionResident ist. Hast du eine Idee? In der ARX Hilfe ist ein Hinwes auf Circle.Break, damit werde ich mal versuchen, was zu finden. Gruss Christian Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Ex-Mitglied
|
erstellt am: 10. Nov. 2009 15:16 <-- editieren / zitieren -->
Hi, ja, jetzt wo du's sagst, da war irgendwas. Da musste ein Elemente mit .Open zum Schreiben geöffnet sein und durfte nicht mit TransAction zum Schreiben verwendet werden, ich seh daheim dann nach. - alfred - ------------------ www.hollaus.at |
Ex-Mitglied
|
erstellt am: 10. Nov. 2009 21:00 <-- editieren / zitieren -->
Hi, andere Funktion wäre 'SwapIdWith', diese läuft auch mit TransAction-Modell. Beispiel zu finden >>>hier<<<: - alfred -
------------------ www.hollaus.at |
Christian Blei Mitglied
Beiträge: 124 Registriert: 23.06.2008 Thinkpad W520, 16GB Win 7,Autocad 2012, ProStructures V8i4+5 , VBA, VB.NET,
|
erstellt am: 11. Nov. 2009 08:18 <-- editieren / zitieren --> Unities abgeben:
Hello Alfred, exactly what I was looking for. Keine Problem mit TransActions die committed werden müssen , um sie dan wieder zu starten und Objekte zu öffnen. XDatas müssen nicht editiert werden. Schön! Da macht .Net (verglichen mit VBA) Laune. russ, Christian Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
| Anzeige.:
Anzeige: (Infos zum Werbeplatz >>)
|