| | |  | Gut zu wissen: Hilfreiche Tipps und Tricks aus der Praxis prägnant, und auf den Punkt gebracht für Autodesk Produkte | | | |  | PRO.FILE 10: So gelingt der Umstieg, eine Pressemitteilung
|
|
Autor
|
Thema: VBA-Problem mit GETENTITY (2914 mal gelesen)
|
peter acad Mitglied
 Beiträge: 9 Registriert: 09.11.2009
|
erstellt am: 09. Nov. 2009 18:56 <-- editieren / zitieren --> Unities abgeben:         
Hallo, ich beiße mir im Moment die Zähne an einem ansich harmlosen Problem aus. Ich nutze zur Auswahl einer Linie folgenden Befehl: object.GetEntity Object, PickedPoint[, Prompt] Ich möchte nach dem Anklicken gern wissen, an welchem Ende ich die Linie berührt habe. Dafür ist eigentlich die Variable "PickedPoint" gedacht. In der Hilfe wird sie wie folgt beschrieben: PickedPoint Variant (three-element array of doubles); output-only A 3D WCS coordinate specifying the point that was selected. Das würde auch sehr einfach zu bestimmen sein, wenn die Angabe WCS für den zurück gegebenen Punkt korrekt sein würde. Diese Angabe ist aber leider falsch. Bei Anwendung im 3D wird als z-Wert immer Null ausgegeben. Ich habe herausgefunden, daß der Rückgabewert nichts anderes als die Koordinate, die ganz links unten in der Statusleiste (Cursor Position) ausgegeben wird, ist. Ich hoffe, daß jemand einen Hinweis zur Umrechnung dieser Werte auf die Punktposition auf der Linie geben kann. Im Moment ist der zurück gegebene Punkt total unbrauchbar. Für Hilfe bedanke ich mich schon einmal im Voraus.
------------------ Gruß Peter Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Ex-Mitglied
|
erstellt am: 09. Nov. 2009 19:08 <-- editieren / zitieren -->
Hi, herzlich willkommen bei CAD-de! Rückfrage: hast Du Objektfang eingeschaltet oder nicht? Wenn nicht, dann überleg mal, wenn Du Schrägriß oder Perspektive aktiv hast (ohne Elemente) und Du zeigst einen Punkt ==> welchen Punkt wird AutoCAD Dir wohl retournieren? ==> Kann nur Z=0 sein, oder. Hast Du Objektfang aktiv, dann nehme ich doch stark an, dass Dir die richtigen z.B. Endpunkt-Koordinaten retourniert werden. Sollte ich nicht recht haben, lass es mich wissen (plus Codeschnipsel von Dir zum Selektieren), wir lauschen hier - alfred - ------------------ www.hollaus.at [Diese Nachricht wurde von a.n. am 09. Nov. 2009 editiert.] |
peter acad Mitglied
 Beiträge: 9 Registriert: 09.11.2009
|
erstellt am: 09. Nov. 2009 20:01 <-- editieren / zitieren --> Unities abgeben:         
Hallo Alfred, danke für die superschnelle Reaktion. Wenn ich einen Punkt mit GETPOINT fangen wollte, würde ich das ja verstehen, aber beim Elemente selektieren sollte das meiner Meinung nach automatisch funktionieren. Ich habe die System-Variable OSMODE beim Programmdurchlauf geprüft. Sie steht auf dem Wert 1 (Endpunkt). Die VBA-Funktion GETENTITY scheint das allerdings nicht zu interessieren. ------------------ Gruß Peter [Diese Nachricht wurde von peter acad am 09. Nov. 2009 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Ex-Mitglied
|
erstellt am: 09. Nov. 2009 20:03 <-- editieren / zitieren -->
Hi Peter, zeig mal den Code-Teil, mit dem Du die Anwender zum Klick aufforderst (samt Variablen-Deklaration), dann probier ich bei mir, wo ich falsch denke (oder wo bei Dir was im Code ersichtlich ist =. - alfred - ------------------ www.hollaus.at |
peter acad Mitglied
 Beiträge: 9 Registriert: 09.11.2009
|
erstellt am: 09. Nov. 2009 20:40 <-- editieren / zitieren --> Unities abgeben:         
Ich hoffe, ich habe alles korrekt wieder gegeben, Einiges habe ich aus dem allgemeinen Deklarationteil holen müssen. Code:
Public Element As Object Public l1_pnt1(0 To 2) As Double Public l1_pnt2(0 To 2) As Double Public pickpnt1(0 To 2) As Double Public startpnt(0 To 2) As Double Public endpnt(0 To 2) As Double Sub trimto() Dim bpnt, spnt As Variant Dim pick As Variant Dim inspnt(0 To 2) As Double Dim lineObj As AcadLine On Error GoTo ende ThisDrawing.SetVariable "BLIPMODE", 1 bpnt = ThisDrawing.Utility.GetPoint(, "select a point: ") inspnt(0) = bpnt(0) inspnt(1) = bpnt(1) inspnt(2) = bpnt(2) On Error GoTo 0 ThisDrawing.SetVariable "BLIPMODE", 0 On Error Resume Next start1: ThisDrawing.Utility.GetEntity Element, pick, Chr(13) + "Select a line" If Element.EntityName = "AcDbLine" Then FillArray Element.StartPoint, startpnt FillArray Element.EndPoint, endpnt l1_pnt1(0) = startpnt(0) l1_pnt1(1) = startpnt(1) l1_pnt1(2) = startpnt(2) l1_pnt2(0) = endpnt(0) l1_pnt2(1) = endpnt(1) l1_pnt2(2) = endpnt(2) ' vom zuerst gefangenen Punkt (bpnt) wird eine Linie rechtwinklig ' auf die selektierte Linie (Element) gezeichnet ' ergebnis -> Punkt schnpnt Call lotpunkt(inspnt, l1_pnt1, l1_pnt2) pickpnt1(0) = pick(0) 'x-wert vom Punkt pick (GETENTITY) pickpnt1(1) = pick(1) 'y-wert vom Punkt pick (GETENTITY) pickpnt1(2) = pick(2) 'z-wert vom Punkt pick (GETENTITY) If distance(l1_pnt1, pickpnt1) < distance(l1_pnt2, pickpnt1) Then Set lineObj = ThisDrawing.ModelSpace.AddLine(schnpnt, l1_pnt2) farbe = Element.color Element.Erase lineObj.color = farbe Else Set lineObj = ThisDrawing.ModelSpace.AddLine(schnpnt, l1_pnt1) farbe = Element.color Element.Erase lineObj.color = farbe End If End If GoTo start1 Exit Sub ende: ThisDrawing.SetVariable "BLIPMODE", 0 On Error GoTo 0 End Sub Public Sub lotpunkt(punkt() As Double, pnt1() As Double, pnt2() As Double) Dim ux, uy, uz, laenge, lambda, dx, dy, dz As Double ' Erstmal den Richtungsvektor ausrechnen ux = pnt2(0) - pnt1(0) uy = pnt2(1) - pnt1(1) uz = pnt2(2) - pnt1(2) ' Dann den Richtungsvektor normieren laenge = Sqr(ux * ux + uy * uy + uz * uz) ux = ux / laenge uy = uy / laenge uz = uz / laenge ' Orthogonal Projizieren lambda = (punkt(0) - pnt1(0)) * ux + (punkt(1) - pnt1(1)) * uy + (punkt(2) - pnt1(2)) * uz ' Lotpunkt ausrechnen schnpnt(0) = pnt1(0) + lambda * ux schnpnt(1) = pnt1(1) + lambda * uy schnpnt(2) = pnt1(2) + lambda * uz End Sub Public Function distance(p1() As Double, p2() As Double) As Double Dim xDist As Double Dim yDist As Double Dim zDist As Double xDist = p1(0) - p2(0) yDist = p1(1) - p2(1) zDist = p1(2) - p2(2) distance = Sqr(xDist ^ 2 + yDist ^ 2 + zDist ^ 2) End Function
Ich habe auf die schnelle noch einige Kommentare eingefügt, damit man erahnen kann, was ich erreichen möchte. Die Funktion trimmt alle selektierten Linien so, daß die neuen Endpunkte mit dem im 3D-Raum gewählten Punkt durch eine Linie verbunden einen rechten Winkel ergeben. Die Fehlerbehandlung der GETENTITY-Funktion funktioniert so nicht, da ich dazu noch Maus- und Tastaturhooks verwendet habe. Diese habe ich aus diesem Code rausgeschnitten. ------------------ Gruß Peter
[Diese Nachricht wurde von peter acad am 09. Nov. 2009 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Ex-Mitglied
|
erstellt am: 09. Nov. 2009 21:10 <-- editieren / zitieren -->
Hi Peter, oh Du hast ja so recht. OSMODE alleine setzen reicht nicht, der Anwender müsste händisch den Objektfang auslösen, dann bekämst Du die richtigen Koordinaten. In Deinem Code würde das bedeuten, der Anwender hätte <Strg><RMT> und dann auf 'Endpunkt' zu gehen bevor er das Objekt selektiert. Ich glaube das wird nicht helfen. Wenn Du jetzt davon ausgehst, dass nicht mehrere Objekte übereinanderliegen (und der Anwender sich mit Zyklus durchtastet), dann hätte ich als Abhilfe zuerst GetPoint (dann wirkt der Objektfang, z.B. '_nea') zu machen und dann ein Selectionset auf den Punkt. Vorsicht, bei naheliegenden Elementen oder übereinanderliegenden Elementen macht das auch Probleme, aber vielleicht hilfts.
Code: Dim tEnt As AcadEntity Dim tPnt As Variant Dim tOsModePrev As Integer tOsModePrev = ThisDrawing.GetVariable("OSMODE") 'vorige Objektfangeinstellung Call ThisDrawing.SetVariable("OSMODE", 512) '_nea tPnt = ThisDrawing.Utility.GetPoint 'holt den Punkt Dim tSelSet As AcadSelectionSet Set tSelSet = ThisDrawing.SelectionSets.Add("TEST") Call tSelSet.SelectAtPoint(tPnt) 'holt das/die Element(e) an dem Punkt Call ThisDrawing.SetVariable("OSMODE", tOsModePrev)
BTW: In der Hilfe über GetEntity steht das auch drin, dass der retournierte Punkt nicht unbedingt am Entity liegt. HTH, - alfred - ------------------ www.hollaus.at |
peter acad Mitglied
 Beiträge: 9 Registriert: 09.11.2009
|
erstellt am: 09. Nov. 2009 21:24 <-- editieren / zitieren --> Unities abgeben:         
Hallo Alfred, vielen Dank für deine Antworten. Ich habe es fast befürchtet. Deine Variante hatte ich auch schon in einer etwas anderen Art angedacht. Mehr als eine Notlösung hatte ich darin nicht gesehen. Die VBA-Funktion GETENTITY nutzt in diesem Fall eine nur zu diesem Zweck vorhandene Variable und die funktioniert nicht, echt traurig. Ich habe gehofft, daß man die Koordinaten unten links irgenwie auf ein anderes Koordinatensystem (WCS) umrechnen kann. Es würde ja auch reichen, die beiden Endpunkte der Linie in das unten links angezeigte System umzurechnen. Nur habe ich im Moment dazu keinen Plan. ------------------ Gruß Peter
[Diese Nachricht wurde von peter acad am 09. Nov. 2009 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Ex-Mitglied
|
erstellt am: 09. Nov. 2009 21:42 <-- editieren / zitieren -->
Hi, >> Ich habe gehofft, daß man die Koordinaten unten links irgenwie auf ein anderes >> Koordinatensystem (WCS) umrechnen kann Du kannst schon ein Benutzerkoordinatensystem erstellen, aber auch hier muss zuerst das Element angeklickt werden, damit Du weisst, wie Du's ausrichten musst. Bei zweimaligem Klick kann man auch gleich eine Variante mit GetPoint und GetEntity kombiniert verwenden. Ich geb aber zu, das Ziel nicht ganz verstanden zu haben. Damit sinkt leider die Anzahl der Ideen bei mir. Mit: >> daß die neuen Endpunkte mit dem im 3D-Raum gewählten Punkt durch eine >> Linie verbunden einen rechten Winkel ergeben konnte ich leider nicht ausreichend verstehen, wohin Du willst. Ev. hast eine kleine Zeichnung mit Status vorher und nachher? - alfred - ------------------ www.hollaus.at |
peter acad Mitglied
 Beiträge: 9 Registriert: 09.11.2009
|
erstellt am: 09. Nov. 2009 21:59 <-- editieren / zitieren --> Unities abgeben:         
|
Ex-Mitglied
|
erstellt am: 09. Nov. 2009 22:03 <-- editieren / zitieren -->
vielleicht überseh ich was, aber lt. Deiner Skizze kann ich mir jetzt nicht vorstellen, dass es bei: - einer gegebenen Linie - einem gegebenen Punkt mehrere Lösungsmöglichkeiten zur Findung des Schnittpunktes geben könnte. Damit ist auch nicht relevant, ob die Linie näher zum Startpunkt oder näher zum Endpunkt angeklickt wird, reicht es da nicht, das Entity zu haben? - alfred - ------------------ www.hollaus.at |
peter acad Mitglied
 Beiträge: 9 Registriert: 09.11.2009
|
erstellt am: 09. Nov. 2009 22:06 <-- editieren / zitieren --> Unities abgeben:         
Ich möchte gern den Punkt der Linie bestimmen, den ich verschieben möchte und welchen ich unverändert lasse. Der gegebene Punkt könnte ja beispielsweise auch relativ mittig zu der Linie liegen. Mir fällt noch etwas zu der Skizze ein. Selektiere ich die Linie am anderen Ende bleibt die rote Linie als Ergenis übrig. ------------------ Gruß Peter [Diese Nachricht wurde von peter acad am 09. Nov. 2009 editiert.] [Diese Nachricht wurde von peter acad am 09. Nov. 2009 editiert.] [Diese Nachricht wurde von peter acad am 09. Nov. 2009 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Ex-Mitglied
|
erstellt am: 09. Nov. 2009 23:16 <-- editieren / zitieren -->
Hi, gültiges Argument. Zwei Ideen hätte ich, ich kann's nur leider mangels Zeit nicht probieren und, noch schlimmer, bin nicht ganz überzeugt, ob's funktioniert. Wenn Du ein paar Minuten dafür hast, sollte sich das aber herausstellen lassen. Vorweg, wird nur funktionieren bei Parallelprojektion (also <> Perspektive). Variante 1: Es gibt in den Utilities die Möglichkeit, mittels 'TranslateCoordinates' Punkte zwischen Weltkoordinatensystem und Display-DCS umzurechnen. Theoretisch sollte ja der mit GetEntity retournierte Punkte WCS sein, wird dieser auf DCS umgerechnet, werden Startpunkt und Endpunkt der Linie auf DCS umgerechnet, dann sollten die Abstände hier Rückschluss darauf zulassen, ob näher den Start- oder dem Endpunkt geklickt wurde. Variante 2: Ein BKS erstellen (durch Start- und Endpunkt der Linie, + 90°Vektor dazu) und damit zum objektbezogenen BKS machen, dann den sollte es auch möglich sein, durch TransFormCoordinates (Umrechnung von WCS auf DCS, dann von DCS auf BKS) den Punkt auf der Linie zu bekommen. Ich hoffe, dass eine der Ideen passt und weit genug gedacht ist. - alfred - ------------------ www.hollaus.at |
peter acad Mitglied
 Beiträge: 9 Registriert: 09.11.2009
|
erstellt am: 10. Nov. 2009 07:39 <-- editieren / zitieren --> Unities abgeben:         
Hallo Alfred, vielen Dank für die beiden Lösungsansätze. Ich denke doch, daß eine der beiden Varianten funktioniert. Mit dem DCS habe ich bereits Transformationsversuche gemacht, allerdings mit unbrauchbaren Ergebnissen. Das liegt aber sicherlich daran, daß ich das DCS noch nicht verstanden habe.  Ich melde mich wieder, wenn ich das Problem aus der Welt geschafft habe.
------------------ Gruß Peter Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Goofy007 Mitglied Vermessungstechniker
  
 Beiträge: 578 Registriert: 06.11.2004 Map3D 2018 und Civil3D 2018
|
erstellt am: 10. Nov. 2009 08:21 <-- editieren / zitieren --> Unities abgeben:          Nur für peter acad
Hallo Peter, Ich hab zwar auf die Schnell dein Problem noch nicht ganz verstanden, aber brauchst du wirklich die Information, auf welcher Seite du die Linie angeklickt hast? Kannst du nicht aus dem Abstand zwischen dem neuen Punkt und den jeweiligen Endpunkten der Linie entnehmen, welches Ende der Linie näher liegt? lg Didi
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
peter acad Mitglied
 Beiträge: 9 Registriert: 09.11.2009
|
erstellt am: 10. Nov. 2009 10:34 <-- editieren / zitieren --> Unities abgeben:         
|

| |
peter acad Mitglied
 Beiträge: 9 Registriert: 09.11.2009
|
erstellt am: 10. Nov. 2009 21:10 <-- editieren / zitieren --> Unities abgeben:         
Hallo, ich habe eine Lösung gefunden. Sie ist so simpel, daß ich nicht verstehen kann, daß man so viel Zeit investieren muß, sie zu finden. Vor der Auswahl der Linie: ThisDrawing.SendCommand "_ucs _v " 'BKS der aktuellen Ansicht Die Koordinaten der Linienendpunkte Lassen sich einfach in das aktuelle BKS der Ansicht umrechnen (nach der Umrechnung müssen die z-Koordinaten beider Endpunkte auf 0 gesetzt werden): bpnt = ThisDrawing.Utility.TranslateCoordinates(bpnt, acWorld, acUCS, False) Jetzt spielt die z-Koordinate keine Rolle mehr und das selektierte Ende der Linie läßt sich einfach bestimmen. Danach das BKS wieder zurückstellen: ThisDrawing.SendCommand "_undo 1 " Erst nach diesem Undo die Befehle für das Löschen und Neuzeichnen der Linie ausführen, ansonsten wird die neu gezeichnete Linie gelöscht. ------------------ Gruß Peter
[Diese Nachricht wurde von peter acad am 10. Nov. 2009 editiert.] [Diese Nachricht wurde von peter acad am 10. Nov. 2009 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
| Anzeige.:
Anzeige: (Infos zum Werbeplatz >>)
 |