Alles in blocks naar laag "0" m.u.v. nested blocks (opgelost)

Gestart door AdenRob, vr 04 10 2013, 16:56:19

Vorige topic - Volgende topic

AdenRob

Beste lezers,

Wij hebben een mooie lisp gevonden op internet (zie: http://www.cadtutor.net/forum/showthread.php?19161-lisp-for-changing-all-objects-in-a-block-to-layer-quot-0-quot) genaamd NORM. Deze lisp vertaald alles wat zich in blocks bevind naar laag “0”.

Nu willen wij deze lisp aanpassen zodat hij alles in blocks vertaald naar laag “0” maar dan met uitzondering van blocks. Als er een block in de tekening zit met bijvoorbeeld 10 lijnen en 2 blocks (nested blocks) dan moeten de 10 lijnen naar laag “0” vertaald worden maar de 2 blocks moeten in de oorspronkelijke laag blijven staan.

Eigenlijk dient er een test functie toegevoegd te worden alvorens alles naar laag "0" vertaald wordt. Deze dient te testen of het object een blocks is of niet. Zo ja, dan moet hij dit niet vertalen naar laag "0".

We hebben in de bijlage de lisp toegevoegd. Bijna onderaan hebben wij een paar regels toegevoegd om te testen of de selectie een block is, echter helaas werkt dit niet... Wat doen wij fout?

Zou iemand ons hier misschien mee kunnen helpen?  :?:

Met vriendelijke groet,
AdenRob

bart

Als je alle blocks aanpast komen de elementen in de geneste blocks altijd in laag 0 te zitten
die blocks ze zitten namelijk ook gewoon los in de database van de tekening

Domme vragen bestaan niet.
Domme antwoorden wel.

m.vr. groet Bart

AdenRob

Dag Bart,

Volgens mij begrijpen we elkaar niet helemaal goed.
De lisp dient wel over de gehele tekeningen, en dus over alle blocks uitgevoerd te worden.

De inhoud van geneste blocks moet dan ook gewoon naar laag "0" vertaald worden, mits de inhoud van het geneste block geen ander genest block is.

Een voorbeeld ter verduidelijking:
We hebben een tekening waarin we de gehele plattegrond als 1 block hebben samengevoegd, zeg maar een overruled block. In dit block zitten honderden andere blocks, maar ook losse lijnen, teksten, maatvoeringen enz. Nu willen we de gehele inhoud van dit overruled block naar laag "0" vertalen, met uitzondering van de honderden blocks. Anders zou dit gehele block van de plattegrond in laag "0" staan en dat willen we niet.
Eigenlijk zou er dus een extra functie ingebouwd moeten worden, alvorens de gehele inhoud naar laag "0" wordt vertaald, die checkt of het object een block is. Uiteraard geldt dit ook voor de honderden geneste blocks (welke misschien ook wel weer een genest block bevatten).
De lisp zou dus simpel gezegd elk block in de tekening moeten openen, alles selecteren binnen dit block m.u.v. blocks, en dan alles naar laag "0" vertalen.

Hopelijk is het zo duidelijk  :D

Alle hulp is van harte welkom!  :vreegoe:

Groeten AdenRob

roy_043

@ AdenRob:
Uit jullie wijzigingen blijkt dat jullie een fundamenteel aspect van blocks niet begrijpen.
Block definities zijn NOOIT genest in andere block definities. Als we het hebben over een 'genest block' zouden we eigenlijk moeten spreken over een block referentie (=INSERT) genest in een block definitie.
Dit is wat Bart probeert uit te leggen.

Om te bereiken wat jullie willen zul je moeten weten welke block referenties in model space zijn geïnsert. En m.b.v. de namen van deze referenties het wijzigen van de block definities moeten controleren.

AdenRob

@ Roy_043:
Weer wat geleerd  :D
Dit verklaard ook waarom onze if-functie niet werkt
(vlax-for subent blk
  (if
    (or
      (/= (vla-get-objectname subent) "AcDbBlockTable")
      )
            (vla-put-layer subent "0")
    )


Wat we alleen niet begrijpen is het volgende:
Bij de standaard NORM Lisp, worden geneste blocks (block referenties) welke zich bevinden in een block definitie wel naar laag "0" vertaald, evenals ALLE andere objecten in de blocks. Dit wil zeggen dat AutoCAD toch een block (insert) herkend, in deze code, wat genest is in een ander block. Of is dit een verkeerde conclusie?

Roy, helaas reikt onze kennis m.b.t. Lisp niet zo ver dat we jouw oplossing direct kunnen vertalen naar een lisp  :(

Welke lisp goeroe zou ons willen helpen om dit probleem op te lossen? Mocht het probleem, aan de hand van onze omschrijving, niet duidelijk zijn dan horen wij het graag.
We posten dan een tekening om een en ander te verduidelijken.

roy_043

Citaat van: AdenRob op di 08 10 2013, 10:58:48
Wat we alleen niet begrijpen is het volgende:
Bij de standaard NORM Lisp, worden geneste blocks (block referenties) welke zich bevinden in een block definitie wel naar laag "0" vertaald, evenals ALLE andere objecten in de blocks. Dit wil zeggen dat AutoCAD toch een block (insert) herkend, in deze code, wat genest is in een ander block. Of is dit een verkeerde conclusie?
Bij het doorlopen van alle block definities worden alle geneste objecten 'vertaald'. Dit is inclusief de geneste block referenties. De inhoud van de block definities waarnaar de block referenties verwijzen wordt echter 'vertaald' omdat alle block definities worden behandeld...


...
(vla-startundomark
  (setq adoc (vla-get-activedocument (vlax-get-acad-object)))
)
(vlax-for obj (vla-get-modelspace aDoc)
  (if (= (vla-get-objectname obj) "AcDbBlockReference")
    (setq nameList (cons (strcase (vla-get-name obj)) nameList)) ; NameList in hoofdletters (kan dubbele namen bevatten).
  )
)
... ; Het wijzigen van de LOCK en FREEZE status van lagen is eigenlijk niet nodig...
...
(if
  (and
    (vl-position (strcase (vla-get-name blockDefObj)) nameList)
    ... ; Controle layout is nu overbodig.
    ... ; Controle xref is nog wel nodig.
  )
  (
    ...
    ...
  )
)
...

AdenRob

Bedankt voor de uitleg, het wordt ons beetje bij beetje duidelijker hoe de lisp werkt!

Uiteraard ook onze hartelijke dank voor je gedeelte van de Lisp!  :vreegoe:

We begrijpen wat hij doet alleen we krijgen deze helaas nog niet werkend op de manier zoals we voor ogen hebben, maar dit zal vast en zeker aan ons liggen.
We zijn de afgelopen dagen erg druk geweest. We gaan dit weekend nogmaals proberen jouw lisp inpasbaar te maken in onze lisp. Je hoort begin volgende week van ons of dit gelukt is! En als het niet gelukt is hoor je het uiteraard ook  :wink:

Prettig weekend alvast!  :pintje:

AdenRob

Helaas krijgen we de lisp maar niet werkend  :(
We hebben veel getest maar ergens maken we een denkfout...

We krijgen op dit moment de volgende foutmelding bij het uitvoeren van de lisp:
bad argument type: VLA-OBJECT nil

We hebben de lisp (met de opmerkingen van Roy_043 hierin verwerkt) toegevoegd in de bijlage. Achter elke regel hebben we getypt wat we verwachten als we de lisp uitvoeren. Hopelijk wordt het op deze manier duidelijk waar onze denkfout zit.

Alle hulp is van harte welkom!

roy_043

(defun C:normNew (/ actDocObj nameList)
  (vl-load-com)
  (vla-startundomark
    (setq actDocObj (vla-get-activedocument (vlax-get-acad-object)))
  )
  (vlax-for obj (vla-get-modelspace actDocObj)
    (if (= (vla-get-objectname obj) "AcDbBlockReference")
      (setq nameList (cons (strcase (vla-get-name obj)) nameList)) ; NameList in hoofdletters (kan dubbele namen bevatten).
    )
  )
  (vlax-for blockDefObj (vla-get-blocks actDocObj)
    (if
      (and
        (vl-position (strcase (vla-get-name blockDefObj)) nameList)
        (= (vla-get-isxref blockDefObj) :vlax-false)
      )
      (vlax-for obj blockDefObj
        (vla-put-layer obj "0")
      )
    )
  )
  (vla-regen actDocObj acallviewports)
  (vla-endundomark actDocObj)
  (princ)
)

AdenRob

Bedankt Roy voor je snelle reactie en lisp!  :vreegoe:

We hebben de lisp getest maar komen er helaas achter dat deze toch niet helemaal doet wat we hebben bedoeld. Wat de lisp doet is de gehele inhoud van alle blocks (inclusief  block referentie (=INSERT) genest in een block definitie :wink:) naar laag "0" vertalen.
Dit is eigenlijk wat de oorspronkelijke NORM-lisp ook al deed.

We denken dat de fout zit in het checken van de blocknaam. De code:
(vl-position (strcase (vla-get-name blockDefObj)) nameList)
zou een nummer als antwoord moeten geven. We willen geneste blocks noujuist niet naar laag "0" vertalen.

We dachten slim te zijn door de code te veranderen naar:
(= (vl-position (strcase (vla-get-name blockDefObj)) nameList) "nil")
als het geslecteerde object nu NIET de naam in de NameList bevat zou hij door moeten gaan met de if-functie. Maar helaas werkt dit ook niet  :(

Wat we ook niet snappen is dat jij, als de and-functie een T geeft, weer de vlax-for gebruikt. Als we het goed begrijpen dan worden hiermee de objecten welke zich IN het geteste block (blockDefobj) bevinden naar laag "0" vertaald. Dit is toch niet nodig? Deze komt toch vanzelf een keer aan de beurt als ALLE blocks in de tekening worden doorlopen? Alleen het geteste object zou naar laag "0" vertaald moeten worden, mits dit geen block is uiteraard!

Hopelijk is het duidelijk wat we bedoelen. Het is een lastig om je te verwoorden als je de lisp-taal niet volledig beheerst   :roll:

PS: Nogmaals onze hartelijke dank voor het mee denken :!:

roy_043

Helemaal begrijpen doe ik het niet meer... Ik ga nu uit van dit scenario:
- De inhoud van alle block definities, moet worden vertaald naar laag '0' m.u.v. eventuele block referenties.
- Layout block definities worden overgeslagen (dit geld ook voor modelspace).
(defun C:normNew2 (/ actDocObj)
  (vl-load-com)
  (vla-startundomark
    (setq actDocObj (vla-get-activedocument (vlax-get-acad-object)))
  )
  (vlax-for blockDefObj (vla-get-blocks actDocObj)
    (if
      (and
        (= (vla-get-islayout blockDefObj) :vlax-false) ; Modelspace wordt overgeslagen.
        (= (vla-get-isxref blockDefObj) :vlax-false)
      )
      (vlax-for obj blockDefObj
        (if (/= (vla-get-objectname obj) "AcDbBlockReference")
          (vla-put-layer obj "0")
        )
      )
    )
  )
  (vla-regen actDocObj acallviewports)
  (vla-endundomark actDocObj)
  (princ)
)

AdenRob

Helemaal geweldig Roy!  :ole: :ole: :ole:

Dit is precies wat we voor ogen hadden!
Uiteraard hebben we je lisp ook deze keer weer bestudeerd. Het leuke is dat we bij onze vraagstlling (eerste post) al een lisp hadden bijgevoegd welke voor 95% op deze lisp lijkt. :D

De fout van ons zat m dus in AcDbblockReference i.p.v. AcDbBlocktable... Ook hadden wij er nog een overbodige or-functie in zitten.  :roll: Desalniettemin zijn alle credits voor jou!

Dit is een gedeelte van onze FOUTE lisp:
(vlax-for blk (vla-get-blocks adoc)
    (if (and (equal (vla-get-islayout blk) :vlax-false)
             (equal (vla-get-isxref blk) :vlax-false)
     )
        (vlax-for subent blk
  (if ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    (or ;;; Dit gedeelte hebben we zelf toegevoegd ;;;
      (/= (vla-get-objectname subent) "AcDbBlockTable") ;;; --------- waar zit de fout? -----------;;;
      ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
          (vla-put-layer subent "0")
    )
          ) ;_ end of vlax-for
      ) ;_ end of if
    )


Ook valt ons op dat jij nog een extra regen hebt toegevoegd.

Nogmaals onze hartelijke dank! Niet alleen voor de lisp, maar zeker ook voor de kennis die je hebt overgedragen  :vreegoe: deze kennis kunnen we zeker gebruiken bij de vele lisps die nog op onze wishlist staan  :wink:

:pintje: Roy

Groeten AdenRob