| |
| Gut zu wissen: Hilfreiche Tipps und Tricks aus der Praxis prägnant, und auf den Punkt gebracht für PTC CREO |
| |
| MAIT übernimmt Kundenstamm von GMCAD, eine Pressemitteilung
|
Autor
|
Thema: LISP: Konfigurationen manipulieren (2821 mal gelesen)
|
holt Mitglied Systembetreuer CAD
Beiträge: 714 Registriert: 07.08.2003 Lenovo ThinkStation P360 Core i7-12700@2.10 GHz, 32GB NVIDIA RTX A2000 12 GB Creo Elements/Direct Modeling 20.3 Creo Elements/Direct Drafting 20.3 Creo Elements/Direct ModelManager 20.3
|
erstellt am: 26. Sep. 2007 15:08 <-- editieren / zitieren --> Unities abgeben:
Hallo, wir verwenden Konfigurationen sehr oft in einem sehr frühen Stadium der Konstruktion an, um verschiedene Stellungen der Mechanik damit abzubilden und Kollisionen zu erkennen bzw. anderen Personen die Situation zu erklären. Wenn dann neue Teile hinzukommen, ist das oft sehr viel Arbeit, diese Teile in den verschiedenen Konfigurationen die gleiche Bewegung machen zu lassen wie Teile, die bereits in der Konfiguration gespeichert sind. Über Baugruppen ist das in den seltensten Fällen lösbar. Meine Idee wäre ein LISP-Programm, welches die Positionsdaten eines Teils aus der Konfiguration ausliest und einem ausgewählten Teil zuweist. Das Auslesen dieser Daten ist ja mittels sd-inq-configuration-positions kein Problem. Aber was mache ich, um diese Daten einem neu in die Konfiguration aufzunehmenden Teil zuzuweisen? Die Daten werden in folgender Form ausgegeben: Code: #S(MATRIX-3D T0 112.23999999999955 T1 -77.000000000000014 T2 592.0 A11 -1.2918958832001823E-16 A12 0.0 A13 -1.0 A21 1.0 A22 1.7629845987893823E-32 A23 -1.2918958832001823E-16 A31 1.7629845987893823E-32 A32 -1.0 A33 -2.2775925453213282E-48 SCALE 1.0 FLAG-1 0 FLAG-2 1 FLAG-3 0 FLAG-4 0 FLAG-5 1 FLAG-6 0)
Kann mir hier jemand einen Tipp geben? ------------------ Gruß aus dem Salzkammergut Thomas Hollerweger Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Michael Kahle Mitglied Programmierer
Beiträge: 75 Registriert: 10.05.2002
|
erstellt am: 27. Sep. 2007 10:08 <-- editieren / zitieren --> Unities abgeben: Nur für holt
Man kann diese Transformation direkt wieder an oli::sd-create-configuration uebergeben und z.B. eine neue Konfiguration mit mehr Teilen anzulegen oder eine bestehende Konfiguration mit zusaetzlichen Teilen zu ergaenzen... ------------------ Viele Gruesse, Michael - http://www.ultra-hip.de -- Spam goes SPAM@CoCreate.com and spam@postini.com ;-) Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
holt Mitglied Systembetreuer CAD
Beiträge: 714 Registriert: 07.08.2003 Lenovo ThinkStation P360 Core i7-12700@2.10 GHz, 32GB NVIDIA RTX A2000 12 GB Creo Elements/Direct Modeling 20.3 Creo Elements/Direct Drafting 20.3 Creo Elements/Direct ModelManager 20.3
|
erstellt am: 27. Sep. 2007 11:19 <-- editieren / zitieren --> Unities abgeben:
Zitat: Original erstellt von Michael Kahle: Man kann diese Transformation direkt wieder an oli::sd-create-configuration uebergeben und z.B. eine neue Konfiguration mit mehr Teilen anzulegen oder eine bestehende Konfiguration mit zusaetzlichen Teilen zu ergaenzen...
Hallo Michael, mit sd-create-configuration bestehende Configurationen ergänzen? Auf diese Idee wäre ich nie gekommen! Das ist doch gar nicht CoCreate-typisch. Sonst gibts ja zu jedem Create-Befehl auch einen Change- oder Modify-Befehl. Ich werds gleich ausprobieren. Danke und 10Us! ------------------ Gruß aus dem Salzkammergut Thomas Hollerweger Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Michael Kahle Mitglied Programmierer
Beiträge: 75 Registriert: 10.05.2002
|
erstellt am: 27. Sep. 2007 12:51 <-- editieren / zitieren --> Unities abgeben: Nur für holt
Ja, das ist halt was Besonderes ;-) Man muss aber schon die alten Daten wieder mit reinfuettern - sonst sind sie weg! Vielleicht auch noch nuetzlich in dem Zusammenhang: (oli::sd-inq-local-object-transformation object) --> TM ------------------ Viele Gruesse, Michael - http://www.ultra-hip.de -- Spam goes SPAM@CoCreate.com and spam@postini.com ;-) Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
der_Wolfgang Moderator Tastenhauer
Beiträge: 2219 Registriert: 3.20. ● PE60+80@home ● W10 Pro Build10.0.19045.4780 ● Drafting V17~V20.7 ● Modeling V17~V20.7 ● Windchill 12.1.2.6 ● UWGM Client 13.0.0.1
|
erstellt am: 01. Okt. 2007 19:25 <-- editieren / zitieren --> Unities abgeben: Nur für holt
Zitat: Original erstellt von Michael Kahle: Man muss aber schon die alten Daten wieder mit reinfuettern - sonst sind sie weg!
zum Mitschreiben: a) (setq my-conf (sd-inq-configuration-props configuration)) b) (sd-create-configuration :Owner (getf my-conf :Owner) :mode (getf my-conf :mode) :attachment (getf my-conf :attachment) :name (getf my-conf :name) :name-conflict :delete-old ;; !! :Positions (nconc (getf my-conf :Positions) new-pos) ;; oder so ähnlich :drawlist (nconc (getf my-conf :drawlist) .....);; oder so ähnlich :camera (getf my-conf :camera) ) Das ist kein modify sondern ein re-create. Aber wird wohl helfen untested!
------------------ Seamonkey Firefox Thunderbird Seamonkey auf deutsch Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
uli1601 Mitglied Konstrukteur
Beiträge: 16 Registriert: 19.07.2007
|
erstellt am: 16. Okt. 2007 19:58 <-- editieren / zitieren --> Unities abgeben: Nur für holt
Hallo allerseits Ich hab mal versucht, die hier getroffenen Vorschläge umzusetzen, um ein LISP zu schreiben, das die Positionsangaben einer Konfiguration einer anderen Konfiguration hinzufügt. Das ist mir auch gelungen, und soweit ich es bisher beurteilen konnte, macht das LISP das, was es soll Aber nun meine Frage: Weiß jemand, wie sich das OSM verhält, wenn in beiden Konfigurationen die gleichen Teile mit unterschiedlichen Positionsangaben versehen sind? Wird da einfach die "ältere" Positionsangabe überschrieben? Hab es zwar schon mal ausprobiert, und anscheinend nimmt OSM einfach die neuere Positionsangabe, aber möglicherweise könnte dies ja irgendwann/jrgendwie Probleme machen??? Hintergrund ist der, das ich mit dem LISP Konfigurationen aus Unterbaugruppen einer Konfiguration in einer Hauptbaugruppe "hinzufügen" möchte. Ich hoffe, dass hier in dem Thread richtig bin, und nicht einen Neuen aufmachen hätte sollen. Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
der_Wolfgang Moderator Tastenhauer
Beiträge: 2219 Registriert: 3.20. ● PE60+80@home ● W10 Pro Build10.0.19045.4780 ● Drafting V17~V20.7 ● Modeling V17~V20.7 ● Windchill 12.1.2.6 ● UWGM Client 13.0.0.1
|
erstellt am: 16. Okt. 2007 20:44 <-- editieren / zitieren --> Unities abgeben: Nur für holt
Hallo Uli, Dein "verschmelzen" ist etwas verschwommen, wenn ich das mal so sagen darf. Intern wird ja eine NEUE Konfiguration erzeugt. Du übergibst nun
Code:
(sd-create-configuration ... :Positions (nconc (getf my-conf :Positions) (getf my-conf_org :Positions)) ...)
was passiert nun wenn das Part 'A' sowohl in my-conf als auch in my-conf_org drin ist? Letzlich will sd-create-configuration EINE position list haben, nun übergibst Du aber 2 (unterschiedliche) positionen für Part 'A'. Woher soll die sd-create-configuration nun wissen, welche position genommen werden soll? Also an der Stelle ist der Code etwas 'fischig', wie Du ja auch schon auf dieses Problem hingewiesen hast. Mag sein das die erste genommen wird, oder die zweite. Aber verläßlich ist das wohl so nicht. Das Verhalten fuer "object ist N mal in Pos-Liste" ist undefiniert! (wenn ich nix überlesen habe) Momentan MAG es so sein, das zur Zeit immer die erste genommen wird (das interpretiere ich mal, wenn Du schreibst "die neuere Positionsangabe"). Aber das ist nicht garantiert! Also man muss wohl die Positions listen auslesen, und dann Object fuer Object wissen, welche position denn nun übernommen werden soll, falls das Object in beiden Listen vorkommt. Analoges gilt wohl fuer die Drawlist. Ich denke der Dialog koennte einen Abschnitt gebrauchen: * Löse Konflikte * (*) Nutze Pos aus Urspung ( ) Nutze Pos aus Ziel ( ) Addiere beide <unschuldig-guck>Ich fürchte, ich habe dich da mit "nconc" auf die flashe Fährte gelockt. Ganz so einfach geht es halt nicht, wenn sich die Objectlisten überschneiden (da fällt mir grad die LISP function intersection zu ein) Ob die option "Addiere beide" sinn macht, mag ich jetzt nicht beantworten. Ausserdem mag ich Transformationen nicht addieren , die sind immer so sperrig. jetzt hab' ich aber viel gesabbelt..
------------------ Seamonkey Firefox Thunderbird Seamonkey auf deutsch Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
uli1601 Mitglied Konstrukteur
Beiträge: 16 Registriert: 19.07.2007
|
erstellt am: 19. Okt. 2007 09:13 <-- editieren / zitieren --> Unities abgeben: Nur für holt
So, hab gestern mal versucht, die gemachten Anmerkungen umzusetzen: Code: (setq my-conf (sd-inq-configuration-props conf)) (setq partsinconf '(1)) (dolist (pos (getf my-conf :Positions)) (nconc partsinconf (list (first pos)))) (pop partsinconf) (display "Parts in Konf_Ziel") (display partsinconf)
Damit möchte ich alle Teile der Konfiguration "conf" herauslesen und diese in der Variable "partsinconf" ablegen. Beim ersten Durchlauf funktioniert dies auch soweit. Wenn ich den LISP-Code allerdings ein zweites Mal aufrufe, wird die Variable "partsinconf" nicht zurückgesetzt (auf "1"), sondern die "alten" Werte des voherigen Aufruf übernommen und die neuen nur angehängt. Beispiel: "partsinconf" nach dem ersten Aufruf des LISPs: ("T1" "T2") "partsinconf" nach dem zweiten Aufruf des LISPs: ("T1" "T2" "T1" "T2") An was kann das liegen? Und ein zweites Problem hab ich noch: Den vorher beschriebenen Code führe ich für beide Konfigurationen durch, und möchte die Ergebnisse mit "intersection" wie vorgeschlagen vergleichen:
Code: (setf schnittmenge (intersection partsinconf partsinconf_org)) (display "Schnittmenge:") (display schnittmenge)
Allerdings bekomm ich dann als Ergebnis nur NIL, obwohl die gleichen Teile drin sind, und die Ausgaben von partsinconf und partsinconf_org gleich sind. Wahrscheinlich werden die beiden Probleme an etwas ganz einfachem liegen aber ich steh irgendwie auf dem Schlauch, und seh nicht, woran es hapert. Würd mich über einen paar Tips freuen Schönen Gruß und vielen Dank Uli
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Markus Kuehl Mitglied
Beiträge: 165 Registriert: 22.06.2001
|
erstellt am: 19. Okt. 2007 15:42 <-- editieren / zitieren --> Unities abgeben: Nur für holt
Hallo Uli, Zitat: Original erstellt von uli1601: ...Wenn ich den LISP-Code allerdings ein zweites Mal aufrufe, wird die Variable "partsinconf" nicht zurückgesetzt (auf "1"), sondern die "alten" Werte des voherigen Aufruf übernommen und die neuen nur angehängt. Beispiel: "partsinconf" nach dem ersten Aufruf des LISPs: ("T1" "T2") "partsinconf" nach dem zweiten Aufruf des LISPs: ("T1" "T2" "T1" "T2") An was kann das liegen?
Das liegt daran, dass Du per nconc die erste Liste (1) destruktiv veraenderst. Initial legst Du mit (setq partsinconf '(1)) eine Liste im LISP Memory an, die ein Element enthaelt (1). Der "Next Pointer" von diesem ersten Element zeigt auf NIL = Ein-elementige Liste. Beim ersten nconc wird allerdings der Next Pointer von diesem ersten Element auf den Anfang von dem zweiten Element umgebogen und somit hat Deine Liste zwei Elemente. Soweit so gut. Das funktioniert auch beim ersten Mal, wie Du bemerkt hast. Wenn Du dann allerdings beim zweiten Mal denkst, dass Du die Liste per (setq partsinconf '(1)) neu initialisiert, so taeuscht Du Dich. Hier wird nur der partsinconf Pointer wieder auf den Anfang der vormals angelegten Liste gelenkt, aber dieses Anfangselement (1) wurde im vorigen Lauf destruktiv veraendert. Das erklaert, warum beim zweiten Mal die alten Elemente noch drin sind. Das kann man ganz einfach beheben, indem man immer eine "frische" Liste beginnt. Ersetze einfach (setq partsinconf '(1)) durch (setq partsinconf (list 1)).
Zitat: Original erstellt von uli1601:
Und ein zweites Problem hab ich noch: Den vorher beschriebenen Code führe ich für beide Konfigurationen durch, und möchte die Ergebnisse mit "intersection" wie vorgeschlagen vergleichen:Code: (setf schnittmenge (intersection partsinconf partsinconf_org)) (display "Schnittmenge:") (display schnittmenge)
Allerdings bekomm ich dann als Ergebnis nur NIL, obwohl die gleichen Teile drin sind, und die Ausgaben von partsinconf und partsinconf_org gleich sind.
Das liegt daran, dass intersection per Default nur mit eql vergleicht. Das reicht fuer Strings nicht. Deshalb muss man noch eine Test Funktion angeben: (intersection a b :test #'sd-string=). Viele Gruesse, Markus
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
uli1601 Mitglied Konstrukteur
Beiträge: 16 Registriert: 19.07.2007 Creo Elements/Direct3D 19.0 MM 19.0 Intel Xeon mit 64GB RAM Windows 7
|
erstellt am: 23. Okt. 2007 19:35 <-- editieren / zitieren --> Unities abgeben: Nur für holt
Vielen Dank Markus und Wolfgang, eure Hinweise und Tips haben mich sehr weitergebracht. Die Bestimmung der gemeinsamen Teile zweier Konfigurationen läuft nun soweit. Nun möchte ich die Teile, die in beiden Konfigurationen vorkommen aus der Zielkonfiguration entfernen: Code: (setf my-conf_pos (getf my-conf :Positions)) (dolist (pos my-conf_pos) (when (not (eql (member (SD-INQ-OBJ-SYSID (first pos)) schnittmenge :Test #'sd-string=) NIL)) (delete pos my-conf_pos)))
In der Variablen "schnittmenge" liegen die Sysids aller in beiden Konfigurationen vorkommenden Teile. Mit dem obigen Code möchte ich diese mit den Sysids der Teile in "my-conf_pos" abgleichen und bei Übereinstimmung das betreffende Teil mit "delete pos my-conf_pos" entfernen. Allerdings funktioniert das nur zum Teil: Sind keine Übereinstimmungen vorhanden wird richtigerwiese kein Teil entfernt. Sind jedoch welche vorhanden, werden alle Übereinstimmungen richtig entfernt mit Ausnahme des ersten Teils in der Positionsliste der Konfiguration. Dieses verbleibt immer in der Liste, egal ob es in der Schnittmenge vorhanden ist, oder nicht. Ich hoffe, die Erklärung war jetzt einigermaßen verständlich. Hier mal ein Beispiel: Drei Teile: T1, T2, T3, alle drei in zwei Konfigurationen =>Schnittmenge T1,T2,T3 Wenn ich nun meinen Code darüberlaufen lasse, sollten ja eigentlich alle Teile aus der Konfigurationsliste entfernt werden. Es werden aber nur T2,T3 entfernt. T1, das an erster Stelle der Liste steht, bleibt in der Liste. Weiß jemand Rat? Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
clausb Ehrenmitglied V.I.P. h.c.
Beiträge: 2914 Registriert: 20.12.2000 Ich schreibe das hier in meiner Freizeit und spreche weder für meinen Arbeitgeber noch für andere Firmen. Mehr Unsinn von mir unter clausbrod.de.
|
erstellt am: 23. Okt. 2007 20:15 <-- editieren / zitieren --> Unities abgeben: Nur für holt
|
der_Wolfgang Moderator Tastenhauer
Beiträge: 2219 Registriert: 3.20. ● PE60+80@home ● W10 Pro Build10.0.19045.4780 ● Drafting V17~V20.7 ● Modeling V17~V20.7 ● Windchill 12.1.2.6 ● UWGM Client 13.0.0.1
|
erstellt am: 24. Okt. 2007 20:10 <-- editieren / zitieren --> Unities abgeben: Nur für holt
Zitat: Original erstellt von uli1601: Vielen Dank Markus und Wolfgang, eure Hinweise und Tips haben mich sehr weitergebracht.
büdde büdde! Damit wir hier noch etwas Lisp lernen/erweitern noch ein kleiner Exkurs.
Code: (Schnittmengenbildung () (dolist (pos my-conf_org_pos) (nconc partsinconf_org (list (SD-INQ-OBJ-SYSID (first pos))))) (pop partsinconf_org) (dolist (pos my-conf_pos) (nconc partsinconf (list (SD-INQ-OBJ-SYSID (first pos))))) (pop partsinconf) (setf schnittmenge (intersection partsinconf partsinconf_org :test #'sd-string=)) );;Schnittmengenbildung
Daran ist nichts ganz falsch.. . Was Claus aber über delete schrieb gilt AFAIK auch fuer nconc (habs' nicht nachgelesen jetzt). Insgesamt baust du 2 komplett neue listen auf, veränderst (reduzierst) dabei 2 andere und bildest aus den ersteren beiden eine weitere neue. Dabei reicht ein einziger Aufruf von intersection. Für den test 2-elemente-sind-gleich, reicht dann aber nicht string=. Da muss was anders her. Das kann man of sehr geschickt mit einem lambda construct machen. (das bietet sicht bei vielen dingen an die auf Listen 'rumnudelen) Code: (setf schnm (intersection list1 list2 #'(lambda (a b) ...))
lambda ist sowas wie ein "on-the-fly-defun" ohne das man einen funktionsnamen spendiert. genau wie vorher string= bekommt lambda zwei parameter, die es zu vergleichen gilt. Bei den Position-Listen einer Configuration besteht ein element immer aus einem Päärchen (object transformation). Also das erste ist das object und davon nehmen wir die SYSID, wie ja oben auch schon. Die sysid vergleichen wir dann wie bisher auch. dann sieht lambda so aus:
Code: (lambda (a b) (sd-string= (SD-INQ-OBJ-SYSID (first a)) (SD-INQ-OBJ-SYSID (first b))))
Die reduzierte Version von Schnittmenge wäre dann:
Code: (Schnittmengenbildung () (setf schnittmenge (intersection partsinconf partsinconf_org :test #'(lambda (a b) (sd-string= (SD-INQ-OBJ-SYSID (first a)) (SD-INQ-OBJ-SYSID (first b)))) );;Schnittmengenbildung
Das mag einem etwas abstract vorkommen ist aber wesentlich kompakter.Allerdings wissen wir bei dieser Method nicht, ob a oder b hinterher in der Schnittmenge sind. Das muss man dabei beachten. Wollen wir wirklich nur die SYSID's haben schieben wir noch ein mapcar hinterher.. wieder mit lambda [code](setf schnittmenge-sysid (mapcar '#(lambda (a) (SD-INQ-OBJ-SYSID (first a))) schnittmenge))/code] Im konkreten Anwendungsfall mag es sogar besser sein erstmal nur die SYSID Listen aufzubauen, mit diesen rumzuhantieren und erst ganz zum schluss die neue configuration part-positionliste aufzubauen. Aber mir ging es ja mal drum LISP alternativen aufzuzeigen. ------------------ Seamonkey Firefox Thunderbird Seamonkey auf deutsch [Diese Nachricht wurde von der_Wolfgang am 24. Okt. 2007 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
uli1601 Mitglied Konstrukteur
Beiträge: 16 Registriert: 19.07.2007
|
erstellt am: 15. Nov. 2007 22:32 <-- editieren / zitieren --> Unities abgeben: Nur für holt
Was lange währt... Nun bin ich endlich mal dazugekommen, mein LISP soweit lauffähig zu machen. Die Vorschläge von dir, Wolfgang werd ich noch mal in ner ruhigen Minute zu Gemüte führen und einbauen, aber wenigstens läuft die Sache soweit. Ursprungskonfiguration auswählen, Zielkonfiguration angeben, und die Positionen der Ursprungskonfiguration werden auf die Zielkonfiguration übertragen, ev. vorhandene dabei überschrieben. Darstellungsliste etc. wird dabei nicht verändert. Vielen Dank, ohne eure Hilfe hätte ich den Code nicht hinbekommen Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
schneewitchen Mitglied Konstrukteur
Beiträge: 120 Registriert: 08.07.2007 HP XW4400 Windows XP Prof. 2002 SP2 Intel(R) Core(TM)2 CPU6400 2x 2,13GHz; 3,25 GB RAM NVIDIA Quadro FX1500 OSD 2006 14.50A (14.50.1.4) ModelManager 14.50A
|
erstellt am: 06. Feb. 2012 10:25 <-- editieren / zitieren --> Unities abgeben: Nur für holt
|
holt Mitglied Systembetreuer CAD
Beiträge: 714 Registriert: 07.08.2003 Lenovo ThinkStation P360 Core i7-12700@2.10 GHz, 32GB NVIDIA RTX A2000 12 GB Creo Elements/Direct Modeling 20.3 Creo Elements/Direct Drafting 20.3 Creo Elements/Direct ModelManager 20.3
|
erstellt am: 06. Feb. 2012 10:56 <-- editieren / zitieren --> Unities abgeben:
|