FastFiber

Lijncontrole uit hele tekening (OPGELOST)

Gestart door Baco, di 25 09 2012, 23:00:51

Vorige topic - Volgende topic

Baco

Wie heeft er een suggestie?

Ik heb een isometrisch schema van een waterleidingstelsel met aan elk einde van een lijn een block met attributen. Deze kan ik exporteren en dan in vabi inlezen. Nu moet elke lijn eindigen met een zo'n block of doorgaan met een andere lijn. Als een lijn dus eindigt zonder block of niet begint met een andere lijn eindigt dus mijn waterleidingstelsel. Nu wil ik mbv een lisp routine controleren waar ik eindpunten van lijnen die niet aangesloten zijn met andere lijnen of blocken.

Wie heeft hier iets voor? Zelf dacht ik alle begin- en eindpunten van elke lijn te filteren en P1, P2, P3 etc te noemen. Dan van elk block het insertionpoint te benoemen en vervolgens de coordinaten te vergelijken  en alle coordinaten die 1x voor komen in de lijst te voorzien van een dikke dot.

Maar hoe kan ik een lijst van punten maken van alle lijnen uit een tekening. En idem dito voor alle blocks.

Bij voorbaat bedankt.

roy_043

Zo bijvoorbeeld:

; (ActiveSet_To_ObjectList)
; Hulpfunctie.
(defun ActiveSet_To_ObjectList ( / activeSet count ret)
  (vlax-for object (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object)))
    (setq ret (cons object ret))
  )
  (reverse ret)
)

; (PointsFromLinesAndInserts)
; Vraagt de gebruiker om een selectie en retourneert een lijst van alle
; insertionpoints (insert) en alle startpoints en endpoints (line).
(defun PointsFromLinesAndInserts ()
  (ssget '((-4 . "<OR") (0 . "INSERT") (0 . "LINE") (-4 . "OR>")))
  (apply
    'append
    (mapcar
      '(lambda (object)
        (cond
          ((= (vla-get-objectname object) "AcDbBlockReference")
            (list (vlax-get object 'insertionpoint))
          )
          ((= (vla-get-objectname object) "AcDbLine")
            (list (vlax-get object 'startpoint) (vlax-get object 'endpoint))
          )
        )
      )
      (ActiveSet_To_ObjectList)
    )
  )
)

Baco

Hoi Roy,

Bedankt voor jouw reactie. Ik ga even regel voor uitzoeken wat er gebeurd. Helaas heb ik thuis geen autocad om te testen. Zelf heb ik diverse lisp-routines geschreven maar dat is alweer een tijd geleden. Nu zie ik dat je het startpunt - eindpunt weer combineert naar een coordinatie. En het insertionpunt van het block ook.

Ik ga even nazoeken op internet en in mijn boek (programmeren in autocad13), ja ik weet het een oud boek.

Jij gebruikt bijv. ook vla en vlax, deze ken ik (nog) niet. Ik zie ook niet zo snel aan welke variabele de lijncoordinaten worden toegekend en aan welke variabele de insertionpoint word toegekend).  Verder zie ook nog niet of het 3D coordinaten zijn of uitsluitend 2D, bovendien kan ik pas maandag even testen......

Alvast bedankt voor jouw inzet!!

Als ik meer weet koppel ik hem hier weer terug.

gr Bas

Baco

#3
Als ik even kijk dan is er 1 lijst met zowel de insertionpoints en begin- en eindpunten van de lijnen. Ik kan nu helaas niet controleren met een tekening en proefdraaien....... mijn vertaling heb ik even achter de lijnen gezet (in kladblok wel goed te lezen). En dan de lijst controleren of de coordinaten 2x voorkomen, dan kan ik ze wegstrepen en de overgebleven een dikke donut geven.

; (ActiveSet_To_ObjectList)
; Hulpfunctie.
(defun ActiveSet_To_ObjectList ( / activeSet count ret) ;maak commando ActiveSet_To_ObjectList
  (vlax-for object (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object))) ;set object "de selectie"
    (setq ret (cons object ret)) ;geef waarde "object" aan ret
  ) ;einde set object
  (reverse ret) ;reverse ret
)

; (PointsFromLinesAndInserts)
; Vraagt de gebruiker om een selectie en retourneert een lijst van alle
; insertionpoints (insert) en alle startpoints en endpoints (line).
(defun PointsFromLinesAndInserts () ;maak commando PointsFromLinesAndInserts
  (ssget '((-4 . "<OR") (0 . "INSERT") (0 . "LINE") (-4 . "OR>"))) ;verkrijg entiteittype
  (apply
    'append ;toevoegen aan de lijst
    (mapcar
      '(lambda (object) ;maak lijst "object"
        (cond ;loop start
          ((= (vla-get-objectname object) "AcDbBlockReference") ;is object een block
            (list (vlax-get object 'insertionpoint)) ;insertionpoint van object
          )
          ((= (vla-get-objectname object) "AcDbLine") ;is object een lijn
            (list (vlax-get object 'startpoint) (vlax-get object 'endpoint)) ;startpoint - endpoint van object
          )
        ) ;loop end
      ) ;eind lijst "object"
      (ActiveSet_To_ObjectList) ;commando
    )
  )
)



groeten Bas

roy_043

Beste Bas,

Jouw analyse van de code is op veel plaatsen niet correct.
Hoog tijd dus om jouw kennis wat op te frissen:
http://www.autolisp-tutorial.mapcar.net/ (Duits)
http://www.afralisp.net/
http://www.cadsite.be/lisp/lisp.php

Als je code in een bijdrage op wilt nemen dan kun je het beste de "#" knop boven het invoerveld gebruiken.

Succes, Roy.

bart

baco,

ter informatie
Als je baas het goed vind is het door autodesk toegestaan om autocad thuis te installeren met de zelfde sleutel als op het werk.

Domme vragen bestaan niet.
Domme antwoorden wel.

m.vr. groet Bart

Baco

Hoi Roy,
Het is inderdaad een tijd geleden dat ik iets met lisp geprogrammeerd heb.... en ik denk ook op een niveau dat minder diep gaat. Ik zal de sites gaan bekijken en de pdf's uitdraaien om het weer op te pakken.

En Bart,
Als dat zo is kan ik er meer aan doen in mij eigen tijd...... zeer nuttige info. Thanks



Baco

Net even de lisp geprobeerd en hij geeft een mooie lijst nadat ik (vl-load-com) had toegevoegd na (defun ActiveSet_To_ObjectList ( / activeSet count ret).

Nu wil ik de lijst gaan controleren op dubbele coordinaten en dan bij de enekel voorkomende een cirkel of donut plaatsen.

Top voor de ondersteuning / start van de code en de "pdf - files" zijn ongeveer wat ik had staan in mijn boek (ik denk het basis van lisp) de overige links ben ik nog niet aan toegekomen......

Tot snel, Bas

Baco

Hoi Roy,

Ik ben erachter dat er ook visual-lisp in de code is toegepast. Hier weet ik niks van :oops:, weet je een duidelijk nederlands boek hierover? Want volgens mij heb ik dat wel nodig om te weten wat ik aan het invoeren ben...... en als je een nederlandse site weet dan is dat ook van harte welkom. Anders moet ik maar zoeken naar een degelijke cursus. :roll:

groeten Bas

roy_043

Er zijn bij mijn weten geen Nederlandse boeken die zich uitsluitend met Lisp bezighouden. Een aantal boeken over Autocad bevat wel een hoofdstuk of twee over het onderwerp, maar van veel diepgang is meestal geen sprake.

Zie hier voor wat voorbeelden:
http://www.cadsite.be/smf/index.php?topic=3807.0

De hierboven reeds genoemde link is een echte aanrader:
http://www.autolisp-tutorial.mapcar.net/

Voor de vl-functies kun je natuurlijk ook gewoon de Help raadplegen:
http://docs.autodesk.com/ACD/2011/ENU/landing.html

Mede n.a.v. jouw PM nog wat tips:

Om punten (= lijsten) te vergelijken kun je alleen (equal) gebruiken. (eq) heeft een hele specifieke betekenis. Ik gebruik deze functie eigenlijk nooit. Ik gebruik of (=) of (equal). Bij (equal) kun je ook een tolerantie opgeven.
(equal '(0 0 0) '(0.01 0.01 0.01) 0.01)
Ik raad je aan om gebruik te maken van een zekere tolerantie. Niet omdat jij onnauwkeurig tekent, maar omdat Autocad niet oneindig nauwkeurig is.

Het idee dat je hebt om elk fout punt op te slaan in een aparte variabele is niet handig. Je kunt Lisp beter gebruiken waar het voor bedoeld is namelijk "LISt Processing".

Ik zou het vervolg van het probleem zo aanpakken:

(setq lst (PointsFromLinesAndInserts))
(while lst
  (setq pointToCheck (car lst))  ; Eerste punt uit de lijst.
  (setq len (length lst))        ; Lengte huidige lijst
  (setq lst                      ; Verwijder alle punten die gelijk zijn aan pointToCheck
    (vl-remove-if
      '(lambda (pointFromList)
        (equal pointFromList pointToCheck 0.001)
      )
      lst
    )
  )
  (if (> (length lst) (- len 2)) ; Vergelijk de lengtes. Er moeten min. 2 punten (w.o. het pointToCheck) uit de lijst zijn verwijderd.
    (CreateDotFunction pointToCheck)
  )
)





Baco

Hoi Roy,

Ik heb hem nu samen gevoegd en het resultaat staat hieronder:
; (ActiveSet_To_ObjectList)
; Hulpfunctie.
(defun ActiveSet_To_ObjectList ( / activeSet count ret) ;maak commando ActiveSet_To_ObjectList
(vl-load-com)
  (vlax-for object (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object))) ;set object "de selectie"
    (setq ret (cons object ret)) ;maak nieuwe lijst
  ) ;einde set object
  (reverse ret) ;keer ret om
)

; (PointsFromLinesAndInserts)
; Vraagt de gebruiker om een selectie en retourneert een lijst van alle
; insertionpoints (insert) en alle startpoints en endpoints (line).
(defun PointsFromLinesAndInserts () ;maak commando PointsFromLinesAndInserts
  (ssget '((-4 . "<OR") (0 . "INSERT") (0 . "LINE") (-4 . "OR>")))        ;selecteer alle lijnen en blocken
  (apply ;laat zien op commandoregel
    'append ;toevoegen aan de lijst
    (mapcar ;maak lijst "object"
      '(lambda (object) ;van elk element uit de lijst "object"
        (cond ;loop start
          ((= (vla-get-objectname object) "AcDbBlockReference") ;is object een block
            (list (vlax-get object 'insertionpoint)) ;insertionpoint van object
          )
          ((= (vla-get-objectname object) "AcDbLine") ;is object een lijn
            (list (vlax-get object 'startpoint) (vlax-get object 'endpoint)) ;startpoint - endpoint van object
          )
        ) ;loop end
      ) ;eind lijst "object"
      (ActiveSet_To_ObjectList) ;commando
    )
  )
  (setq lst (PointsFromLinesAndInserts)) ;lst = PointsFromLinesAndInserts
  (while lst ;als lst is niet gelijk aan nil
  (setq pointToCheck (car lst))  ; Eerste punt uit de lijst.
  (setq len (length lst))        ; Lengte huidige lijst
  (setq lst                      ; Verwijder alle punten die gelijk zijn aan pointToCheck
    (vl-remove-if
      '(lambda (pointFromList)
        (equal pointFromList pointToCheck 0.001)
      )
      lst
    )
  )
  (if (> (length lst) (- len 2)) ;vergelijk de lengtes. Er moeten min. 2 punten (w.o. het pointToCheck) uit de lijst zijn verwijderd.
    (CreateDotFunction pointToCheck) ;zet dot?
  )
  )
)

;


Dit geeft als resultaat een oneindige loop. (hij begint telkens weer bij selecteer) en volgens mij komt het doordat lst=nil

Verder zal het mij nog wel een aantal avondjes kosten.... bedankt voor jouw ondersteuning! ps ik ga ff pitten... de kids staan 6:00h weer naast mijn bed :shock:.


mvg Bas

roy_043

Jouw oplossing komt inderdaad in een oneindige lus terecht. De reden hiervoor is recursie. De functie (PointsFromLinesAndInserts) roept zichzelf aan. Mits goed gebruikt kan recursie zeer nuttig zijn. Maar hier gaat het dus mis.

Hieronder mijn bedoeling. De functie (MarkPoint) moet nog uitgewerkt worden.

; 20121004: Toegevoegd. Nodig voor Autocad (maar niet voor Bricscad).
(vl-load-com)

; 20121004: Overbodige variabelen verwijderd.
; 20120926
; (ActiveSet_To_ObjectList)
; Hulpfunctie om de actieve selectie om te zetten in een lijst met objecten.
(defun ActiveSet_To_ObjectList ( / ret)
  (vlax-for object (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object)))
    (setq ret (cons object ret))
  )
  (reverse ret)
)

; 20121004
; (MarkPoint)
; Hulpfunctie om een punt te markeren.
; Deze functie moet nog gemaakt worden.
; Nu worden alleen de coördinaten van het punt weergegeven.
(defun MarkPoint (point)
  (print point)
)

; 20121004: De functie (PointsFromLinesAndInserts) is geïntegreerd in deze nieuwe functie.
; (c:CheckWaterLines)
; Hoofdfunctie.
(defun c:CheckWaterLines ( / len lst pointToCheck)
  (if (ssget '((-4 . "<OR") (0 . "INSERT") (0 . "LINE") (-4 . "OR>")))
    (setq lst
      (apply
        'append
        (mapcar
          '(lambda (object)
            (cond
              ((= (vla-get-objectname object) "AcDbBlockReference")
                (list (vlax-get object 'insertionpoint))
              )
              ((= (vla-get-objectname object) "AcDbLine")
                (list (vlax-get object 'startpoint) (vlax-get object 'endpoint))
              )
            )
          )
          (ActiveSet_To_ObjectList)
        )
      )
    )
  )
  (while lst
    (setq pointToCheck (car lst))  ; Eerste punt uit de lijst.
    (setq len (length lst))        ; Lengte huidige lijst
    (setq lst                      ; Verwijder alle punten die gelijk zijn aan pointToCheck
      (vl-remove-if
        '(lambda (pointFromList)
          (equal pointFromList pointToCheck 0.001)
        )
        lst
      )
    )
    (if (> (length lst) (- len 2)) ; Vergelijk de lengtes. Er moeten min. 2 punten (w.o. het pointToCheck) uit de lijst zijn verwijderd.
      (MarkPoint pointToCheck)
    )
  )
  (princ)
)

Baco

Roy,

Je bent een toppertje. Ik ben blij dat je een forum-verslaafde bent...... Ik heb zelf nog wel veel werk om het goed uit te zoeken water per regel gebeurt. De code zal ik hier en daar wat aanpassen zoals een apparte laag voor de circels. Het meeste snap ik wel nu ik er weer ff mee bezig ben maar volgens mij is hetgene wat ik niet begrijp visual-lisp. Hier zal ik toch gaan zoeken naar een begeleidend boek in de nederlandse taal. Wat ik ook niet wist is dat het commando circle op meerdere punten tegelijk een circel zet.

Mijn grote dank,
Bas :mrgreen:

roy_043

Citaat van: Baco op do 04 10 2012, 19:34:37Wat ik ook niet wist is dat het commando circle op meerdere punten tegelijk een cirkel zet.
Dat wist ik ook niet... M.a.w. volgens mij klopt dit niet.

EddyBeerke

Citaat van: Baco op do 04 10 2012, 19:34:37
...
volgens mij is hetgene wat ik niet begrijp visual-lisp...
Als ik het goed heb is Lisp een engelstalige programmeertaal.
Het zou dus  niet verkeerd zijn om je engels wat bij te schaven.
Als je dus wat meer van Visual-Lisp wilt weten:
http://ubuntuone.com/p/uUb/
Kijk het eens na want er wordt soms ook vergeleken met Auto-Lisp
Civil3d 2026, Blender 4.x gebruiker
Gebruiker sinds AutoCAD R12

http://eddylucas.c1.biz/
https://www.google.com/maps/contrib/109381066561676463628/photos/

yoin