AutoLisp ile Basit Bir Blok Sayacı

Giriş

Bu makalemde, sizlere kullanıcıdan bir blok referansları seçilmesini isteyecek ve seçimdeki her bloğun adedini AutoCAD komut satırında görüntületecek basit bir blok sayaç programını AutoLISP’de nasıl oluştururacağınızı adım adım anlatacağım.

Ders, blok adlarını ve bunlarla ilişkili miktarları kaydetmek için uygun bir ilişki listesi oluşturarak blokları nasıl sayacağımızı gösterecektir – bu kavram, daha sonra, verilerin kayıt ve güncelleştirilmesini içeren diğer uygulamalara da uygulanabilir.

Bu makale, AutoLISP dilini ve söz dizimini basit bir şekilde anlayanlara yöneliktir ve yeni başlayanlar için yazılan çoğu öğreticinin aksine, nihai sonuç verecek olan gerçek dünyadan çizim örneğini de içermektedir.

.

Temel Çerçeve

Aşağıdaki adımlarda öncelikle blok sayıcı programı için temel bir çerçeve oluşturacağız: AutoCAD‘in komut satırından çağrılabilecek bir fonksiyon tanımlanması aşağıdaki adımları içerecektir:

  • Fonksiyon tanımlanması
  • Sayılacak bloklar için seçim setinin elde edilmesi
  • Seçim seti üzerinde yineleme vasıtası oluşturulması

Fonksiyonu Tanımlama

İlk adım olarak, blok sayma işlemlerini gerçekleştirecek bir fonksiyon olan myblockcounter fonksiyonunu tanımlayacağız:

 

(defun c:myblockcounter ( / ) ;Fonksiyonu tanımlama

) ;defun fonksiyonu sonu

Fonksiyon isminin önüne c: ön ekini ekleyerek; fonksiyonun AutoCAD komut satırında bu c: önekinden sonra gelen myblockcounter ifadesini komut olarak işleme almasını sağlayalım.

Seçim Setini Elde Etme

Fonksiyon tarafından gerçekleştirilecek ilk işlem, sayılmak üzere bir blok seçim seti elde etmektir – bunun için ssget fonksiyonunu kullanacağız.

ssget fonksiyonu, kullanıcıdan veya otomatik olarak birden çok nesnenin seçimini elde etmek için, kullanılabilen genel bir seçim fonksiyonudur (buraya tıklayarak bu fonksiyon tarafından sunulan tüm seçenekleri ayrıntılı olarak bulabilirsiniz).

(defun c:myblockcounter ( / ) ;Fonksiyonu tanımlama

    (ssget) ;Kullanıcıyı seçin yapması için, uyarma ve şayet seçim yapıldıysa, seçim setini geri döndürme

) ;defun fonksiyonu sonu

Ssget fonksiyonu defun ifadesinde değerlendirilen son ifade olduğundan ve bu nedenle ssget fonksiyonu tarafından döndürülen herhangi bir değer defun ifadesi tarafından da geri döndürüleceği için, bu değerlerin komut satırına döndüğüne dikkat edin.

Bununla birlikte, durduğu gibi, değer şu anda bir değişkene atanmadığından ve programın herhangi bir yerinde atıf yapılamayacağı için, ssget fonksiyonu tarafından döndürülen seçim kümesini kullanamayız. Bu yüzden, ssget fonksiyonu tarafından döndürülen değeri sel sembolüne atayacağız.

 

(defun c:myblockcounter ( / ) ;Fonksiyonu tanımlama, yerel değişkenleri bildirme.

(setq sel ;Aşağıdaki ifade tarafından geri döndürülen değeri ‘sel’ isimli sembole atar.

(ssget) ;Kullanıcıyı seçin yapması için, uyarma ve şayet seçim yapıldıysa, seçim setini geri döndürme

) ;setq fonksiyonu sonu

) ;defun fonksiyonu sonu

Aynı zamanda, sel sembolünün , defun ifadesinin sembol listesindeki c: myblockcounter fonksiyonunun yerel bir değişkeni olarak ta deklare edildiğine dikkat edin.

Geçerli kod kullanıcıya herhangi bir nesneyi seçme imkanı vermesine rağmen, bu seçimi sadece uygun bir ssget  filtre listesi argümanını kullanarak blok referanslarına izin verecek şekilde hassaslaştırabiliriz:

 

(defun c:myblockcounter ( / ) ;Fonksiyonu tanımlama.

    (setq sel ;Aşağıdaki ifade tarafından geri döndürülen değeri ‘sel’ isimli sembole atar.

        (ssget ;Kullanıcıyı seçim yapması için, uyarma ve şayet seçim yapıldıysa, seçim setini geri döndürme.

‘((0 . “INSERT”)) ;Seçimi sadece blok referansları için filitreleme (INSERTs)

) ;ssget fonksiyonu sonu.

 ) ;setq fonksiyonu sonu.

) ;defun fonksiyonu sonu 

Son olarak, blokları seçme işlemini denemeye başlamadan önce, kullanıcının geçerli bir seçim yapıp yapmadığını kontrol etmeliyiz ya da kullanıcının blok referanslarını seçmeyerek veri istemini (uyarıyı) gözden kaçırıp kaçırmadığını kontrol etmeliyiz.

Bunun için bir if ifadesi kullanabiliriz:

(defun c:myblockcounter ( / ) ;Fonksiyonu tanımlama, yerel değişkenleri bildirme.

(if ;Şayet aşağıdaki ifade boş olmayan “non nil” bir değer geri döndürürse,

 (setq sel ;Aşağıdaki ifade tarafında geri döndürülen değeri ‘sel’ sembolüne ata.

            (ssget ;Kullanıcıyı seçim yapması için, uyarma ve şayet seçim yapıldıysa, seçim setini geri döndürme

               ‘((0 . “INSERT”)) ;Seçimi sadece blok referansları için filitreleme (INSERTs)

            ) ;ssget fonksiyonu sonu.

        ) ;setq fonksiyonu sonu.

        “Seçim geçerli.”;Then seçim geçerlidir.

        “Seçim geçerli değil.”;Else seçim geçerli değildir.

    ) ;if döngüsü sonu.

) ;defun fonksiyonu sonu.

Yukarıdaki programı deneyin; şayet geçerli bir seçim yapıldıysa, fonksiyon then argümanının sonucunu döndürür. Aksi halde else argümanı döndürülür.

Not: AutoLISP’de, test ifadesi boş “nil” olmayan bir değer döndürürse, (böyle bir if  ifadesi gibi) koşullu ifadenin doğrulanmış olacağını- yani, test ifadesinin mutlaka T veya Doğru “True” ifadesini açıkça döndürmesinin gerekmediğini not edin. Aşağıdaki örneği gözden geçirin.

(setq var 1)

(if var

(princ “Bunu yap.”)

(princ “Aksi halde şunu yap.”)

)

Burada, test ifadesi yalnızca var sembolüdür – bu sembol, atanmış olabilecek herhangi bir değeri vermek için if  fonksiyonu ile değerlendirilir. Yukarıdaki örnekte, var sembolü 1 değerine atanmış bir değişkendir. 1, boşa “nil” eşit olmadığından, if  ifadesi doğrulanmış olur ve then bağımsız değişkeni değerlendirilir.

Seçimi İşleme

Artık fonksiyonu tanımlandıktan ve kullanıcıdan bir blok seçimi elde ettiğimize göre, programın her ayrı bloğun oluşum sayısını saymak için seçim üzerinde yinelemesine ihtiyacı olacaktır.

Bunun için, en yüksek dizindeki öğeden başlayarak, kümedeki her bir öğeyi işlemek için repeat ifadesi kullanan önceki AutoLisp Programını Döngüleme isimli makalemde anlatmış olduğum yöntemi kullanabilirsiniz.

Şimdi, repeat fonksiyonunu mevcut kodumuza dahil ederek devam edelim:

 

(defun c:myblockcounter ( / ) ;Fonksiyonu tanımlama, yerel değişkenleri bildirme.

    (if ;şayet aşağıdaki ifade boş “nill” olarak dönmezse,         

(setq sel ;aşağıdaki ifade tarafından geri döndürülen değeri sel sembolüne ata.           

(ssget ;Kullanıcıyı seçim yapması için, uyarma ve şayet seçim yapıldıysa, seçim setini geri döndürme              

‘((0 . “INSERT”)) ;Seçimi sadece blok referansları için filitreleme (INSERTs)           

) ;ssget fonksiyonu sonu       

) ;setq fonksiyonu sonu       

(repeat ;Parantezler arasındaki ifadeyi sel sembolüne atanan sayı kadar tekrar et.           

(sslength sel;Seçim setindeki eleman sayısını geri döndürür       

) ;repeat fonksiyonu sonu   

) ;if test döngüsü sonu

) ;defun fonksiyonu sonu

Burada repeat fonksiyonu if test ifadesinin then argümanıdır; Kullanıcıya herhangi bir nesne seçilmediğini bildirmenin gerekli olmadığını düşündüğüm için, (kullanıcının bunu zaten biliyor olması gerekiyor!) else argümanını atladım.

sslength ifadesi, sel  seçim setimizdeki öğelerin sayısını döndürür ve bu nedenle, repeat fonksiyonu, parantezler arasındaki ifadeleri, kullanıcı tarafından seçilen nesnelerin sayısına eşit sayıda kez her seçilen blok referansını işleyerek değerlendirir.

Bu noktada, sslength ifadesinin if ifadesinin kullanılmasının nedeni olduğunu belirtmek gerekir: şayet sel  değişkeni boş “nil” ise, (sslength sel) ifadesi yanlış argüman “bad argument“ türü: lselsetp nil) hata mesajını döndürecektir, if test ifadesi sadece (sslength sel) fonksiyonunda sel sembolünün boş olmayan “non nil” değere sahip olmaması ve dolayısıyla geçerli bir seçim kümesi içerdiğinden emin olunmasını sağlar.

Şimdi Yöntem 2a yapısıyla devam edelim:

idx dizin değişkenini tanımlayabilir ve seçim kümesindeki her dizindeki blok referans öğesine erişebiliriz:

(defun c:myblockcounter ( / idx sel ) ;Fonksiyonu tanımlama, yerel değişkenleri bildirme.   

(if ;Şayet aşağıdaki ifade boş olmayan “non-nil” bir değer döndürürse       

(setq sel ;Aşağıdaki ifade tarafından geri döndürülen değeri ‘sel’ sembolüne ata.           

(ssget ;Kullanıcıyı seçim yapması için, uyarma ve şayet seçim yapıldıysa, seçim setini geri döndürme              

‘((0 . “INSERT”)) ;Seçimi sadece blok referansları için filitreleme (INSERTs)           

) ;ssget fonksiyonu sonu       

) ;setq fonksiyonu sonu       

(repeat ;Parantezler arasındaki ifadeyi sel sembolüne atanan sayı kadar tekrar et.           

(setq idx ;Aşağıdaki ifade tarafından geri döndürülen değeri ‘idx’ sembolüne atama.               

(sslength sel) ;Seçim setindeki öğe sayısını geri döndürme.           

) ;setq fonksiyonu sonu.  

(print ;(sadece test amaçlı olarak) aşağıdaki ifadeyi komut satırına yazdırma.               

(ssname sel ;Aşağıdaki endeks numarasına sahip varlığı elde etme.                   

(setq idx (1- idx)) ;(Seçim seti indeksi sıfırdan başladığı için index değişkeninin değerini azaltma.               

) ;ssname fonksiyonu sonu.           

) ;print fonksiyonu sonu.       

) ;repeat fonksiyonu sonu.   

) ; if döngüsü sonu.

) ;defun fonksiyonu sonu.

Şayet yukarıdaki programı çalıştırırsak, bir dizi blok seçtiğimizde, seçimdeki her varlık adı AutoCAD  komut satırına yazdırılacaktır; ancak merak uyandırıcı bir şey göreceksiniz: üç blok referansının seçilmesi dört varlık adının yazdırılmasına neden olacaktır Komut satırında, son varlık adı tekrarlanır. Örneğin:

Command: myblockcounter

Nesneleri seç: “Select objects:”  Karşı köşeyi belirleyin: 3 nesne bulundu. “Specify opposite corner: 3 found.”

 Nesneleri seç: “Select objects:”

<Varlık adı: “Entity name:” 7ffff7101f0>

< Varlık adı: “Entity name:” 7ffff710200>

< Varlık adı: “Entity name:” 7ffff710290>

< Varlık adı: “Entity name:” 7ffff710290>

Endişelenmeyin! – Bu repeat  fonksiyonu ile oluşan bir hata değildir.

repeat  fonksiyonu, kapalı ifadeleri belirli bir sayıda değerlendirir ve daha sonra en son değerlendirilen ifade tarafından döndürülen değeri geri döndürür. Bizim durumumuzda, son değerlendirilen ifade, kendisine sağlanan değeri (yani varlık adı) döndürecek olan basma ifadesidir.

If fonksiyonu ‘then’ veya ‘else’ argümanları tarafından döndürülen değeri geri döndürecektir, bu nedenle, bizim durumumuzda, bu repeat  fonksiyonu tarafından döndürülen değerdir (yani varlık adıdır).

Son olarak, defun ifadesi, fonksiyon tanımında değerlendirilen son ifadeyle döndürülen değeri geri döndürür – tabi ki bu değer if fonksiyonu tarafından döndürülen değer ve dolayısıyla ek varlık adıdır.

Bu değeri geri dönmekten kaçınmak için, fonksiyon tanımında değerlendirilen son ifadenin hiçbir şey döndürmediğinden emin olmamız yeterlidir (örn. Boş bir sembol). Bunun için princ veya prin1 ifadelerini kullanabilirsiniz:

 

(defun c:myblockcounter ( / idx sel ) ;Fonksiyonu tanımlama, yerel değişkenleri bildirme.

(if ;Şayet aşağıdaki ifade boş olmayan “non nil” bir değer geri döndürürse,       

(setq sel ;Aşağıdaki ifade tarafından geri döndürülen değer ‘sel’ sembolüne atanır.           

(ssget ;Kullanıcıyı seçim yapması için, uyarma ve şayet seçim yapıldıysa, seçim setini geri döndürme              

‘((0 . “INSERT”)) ;Seçimi sadece blok referansları için filitreleme (INSERTs)           

) ;ssget fonksiyonu sonu       

) ;setq fonksiyonu sonu       

(repeat ;Parantezler arası ifadeyi aşağıdaki sayı kadar tekrarlama:           

(setq idx ;Aşağıdaki ifade tarafından geri döndürülen değeri ‘idx’ sembolüne atama.               

(sslength sel) ;Seçim setindeki öğe sayısını geri döndürme.            

) ;setq fonksiyonu sonu           

(print ;(test amaçlı olarak) aşağıdaki ifadeyi komut satırına yazdırma.               

(ssname sel ;aşağıdaki endeks numarasına sahip varlığı elde etme.                   

(setq idx (1- idx)) ;(Seçim seti indeksi sıfırdan başladığı için) index değişkeninin değerini azaltma.               

) ;ssname fonksiyonu sonu           

) ;print fonksiyonu sonu       

) ;repeat fonksiyonu sonu   

) ;if döngüsü sonu   

(princ) ;(if döngüsünün) son geri döndürdüğü ifadeyi engelleme.

) ;defun fonksiyonu sonu

Seçimdeki her bir bloğun oluşumlarını kaydetmek için ilişki listesini oluşturmadan önce son adım olarak önce her bloğun adını edinmeliyiz.

Blok adı, ilişkilendirme listesindeki her bir öğe için ‘anahtar’ olarak kullanılır ve seçimdeki blok adının oluşum sayısına karşılık gelen ilişkili bir tam sayı değeri kullanılır.

Varlığın herhangi bir özelliğini elde etmek için, varlık için veri tabanında saklanan DXF verilerini sorgulayabiliriz (varlığın adı sadece bu DXF verisine bir işaretçidir) – Bu veriyi elde etmek için, entget fonksiyonu kullanılır.

entget fonksiyonu tarafından döndürülen DXF verileri kendisinin bir birlik listesi: herhangi bir sayıda alt listeyi içeren bir liste, her alt liste iki veri öğesi içerir: bir ‘anahtar’ ve bununla ilişkili değer. Bu tür alt listeler eş çiftler olarak bilinir.

Blok referans varlık için blok adı, DXF grup 2 ile ilişkili değer, yani birinci öğe tamsayı 2 olan alt liste ile ilişkili değerdir.

Bu maddeyi DXF veri ilişkilendirme listesinden elde etmek için ilişkili değeri elde etmek için cdr komutu ile birleştirilmiş assoc fonksiyonunu kullanabiliriz, bu değer daha sonra yerel bir blk değişkenine atanabilir:

 

(defun c:myblockcounter ( / idx sel ) ;Fonksiyonu tanımlama, yerel değişkenleri bildirme   

(if ;Şayet aşağıdaki ifade boş olmayan “non nil” bir değer geri döndürürse,       

(setq sel ;Aşağıdaki ifade tarafından geri döndürülen değer ‘sel’ sembolüne atanır.           

(ssget ;Kullanıcıyı seçim yapması için, uyarma ve şayet seçim yapıldıysa, seçim setini geri döndürme                

‘((0 . “INSERT”)) ;Seçimi sadece blok referansları için filitreleme (INSERTs)          

) ;ssget fonksiyonu sonu        

) ;setq fonksiyonu sonu       

(repeat ;Parantezler arası ifadeyi aşağıdaki sayı kadar tekrarlama:           

(setq idx ;Aşağıdaki ifade tarafından geri döndürülen değeri ‘idx’ sembolüne atama.               

(sslength sel) ;Seçim setindeki öğe sayısını geri döndürme.        

) ;setq fonksiyonu sonu           

(setq blk ;Blok isimlerini ‘blk’ değişkenine atama.               

(cdr ;DXF grup 2 (blok ismi) ile ilişkili değeri elde etme.                   

(assoc 2 ;Aşağıdaki DXF verilerinden DXF grup 2 eş çiftlerini elde etme.                       

(entget ;Aşağıdaki varlık için, DXF veri listesini elde etme.                           

(ssname sel ;Aşağıdaki endeks numarasındaki varlığı elde etme.                               

(setq idx (1- idx)) ;(Seçim seti indeksi sıfırdan başladığı için) index değişkeninin değerini azaltma.                           

) ; ssname fonksiyonu sonu.                       

) ;entget fonksiyonu sonu.                   

) ;assoc fonksiyonu sonu.               

) ;cdr komutu sonu.           

;setq fonksiyonu sonu

(print blk) ;(test amaçlı olarak) blok ismini komut satırına yazdırma.       

) ;repeat fonksiyonu sonu.   

) ;if döngüsü sonu.   

(princ) ;(if döngüsünün) son geri döndürdüğü ifadeyi engelleme.

) ;defun fonksiyonu sonu.

Yukarıdakileri test ettikten sonra, komut satırına yazdırılan her seçili blok referans için blok adını göreceksiniz.

Bunun seçimdeki dinamik blok referansları için anonim blok adları döndürebileceğini unutmayın: Bu dinamik blok yapılırken, dinamik blok parametreleri orijinal blok tanımında tanımlanan referanslar değiştirilerek elde edilmesinden kaynaklanmaktadır.

Eleman Listelerinin Arka Planı

Artık blok sayıcı programımız için temel çerçeveye sahibiz, şimdi ana blok sayma motorunu (ilişkilendirme listesini) oluşturacağız:

Eleman Listesi Nedir?

Bir ilişkilendirme listesi tipik olarak eşçiftlerin bir listesidir: her eş çift ilk öğe olarak bir ‘anahtar’ ve ikinci öğe olarak ilişkili bir değere sahiptir. Genel anlamda, AutoLISP’deki bir ilişkilendirme listesi herhangi bir listenin alt listesi olabilir.

Aşağıda, eş çiftlerin bir ilişkilendirme listesinin basit bir vardır ve bu liste kelimenin tam anlamıyla kesme işareti kullanılarak tanımlanmıştır:

(setq alist

    ‘(       

         (“Item 1” . “Value 1”)       

         (“Item 2” . “Value 2”)       

          (“Item 3” . “Value 3”)   

    )

)

Anahtarların ve ilişkili değerlerin mutlaka dizgeler olması gerekmediğini unutmayın – AutoLISP dinamik olarak yazılmış olduğundan bunlar herhangi bir AutoLISP veri türü olabilir ve ayrıca ilişkilendirme listesindeki öğeler de değişken türdeki verileri içerebilir.

Bir ilişkilendirme listesindeki anahtarların da benzersiz olması gerekmez (örnek olarak, bir SÜREKLİ ÇİZGİ “POLYLINE” öğesi için vertex DXF verilerini düşünün); ancak, şayet anahtarlar benzersizse, genellikle daha kullanışlı olacaktır.

Bir Eş Çift Oluşturma

Standart bir AutoLISP listesinin aksine, eş çift, hafızada saklanma biçiminde farklılık gösteren özel bir liste şeklidir.

ok fazla ayrıntıya girmeden, AutoLISP’deki standart bir liste Bağlı Liste olarak bilinir. Listedeki her öğe iki bellek konumu (kayıt) gerektirir: Birincisi (adres kaydı olarak bilinir) liste öğesinin değerini depolar; ikinci (azalma kaydı olarak bilinir) listede bir sonraki öğenin adres kayıt defterinin adresini veya adresini veren bir işaretçi depolar.

Her kayda erişmek için car (Adres Kayıt İçeriği “Contents of Address Register”) ve cdr (Azalma Kayıt İçeriği “Contents of Decrement Register”) fonksiyonlarına sahibiz. Bu nedenle standart bir liste için, car fonksiyonu listedeki ilk öğeyi döndürür ve cdr fonksiyonu listenin geri kalanını döndürür:

 

_$ (setq lst ‘(1 2 3 4 5))

(1 2 3 4 5)

_$ (car lst)1_$ (cdr lst)

(2 3 4 5)

Eş çiftler her liste öğesi için iki bellek kayıt defteri işgal etmek yerine eş çift anahtarı tek bir kayıt yeri kaplar ve ilişkili değer ikinci bir bitişik kayıt kaplar nitelikte olduğundan, standart listelerden farklıdır. Dolayısıyla, car fonksiyonu eş çiftin ilk öğesini (anahtar) yine de döndürecek olsa da, cdr fonksiyonu artık eş çiftin ikinci öğesini (ilişkili değer) bir liste değilse döndürür:

_$ (setq dpair ‘(1 . 2))

(1 . 2)

_$ (car dpair)1_$ (cdr dpair)

2

Standart bir liste oluşturulmasına benzer şekilde, cons fonksiyonunu kullanarak bir eş çift oluşturabiliriz. cons fonksiyonuna verilen ikinci argüman bir atom (liste dışı veri öğesi) olduğunda, cons fonksiyonu bir eş çift döndürür:

_$ (cons 1 2)

(1 . 2)

İlişkilendirme Listesi Oluşturma

Yukarıdaki örneklerde, ilişkilendirme listeleri bir önünde kesme işareti () bulunan gerçek ifadeler olarak tanımlanmıştır- bu yaklaşım sabit veriler için gayet iyi olmakla birlikte; veri bilinmediğinde ve değişken olduğunda, listenin çalışma zamanında oluşturulması gerekir.

Bir ilişkilendirme listesi, cons fonksiyonu kullanılarak standart bir liste veya eş çift ile aynı şekilde oluşturulabilir: cons fonksiyonuna verilen ikinci argüman bir liste olduğunda, cons fonksiyonu ilk argümanı listenin önüne ekler (iter):

 

_$ (cons 1 ‘(2 3 4 5))

(1 2 3 4 5)

Bu şekilde, eş çiftleri tekrar tekrar bir listeye iterek bir ilişkilendirme listesi oluşturabiliriz:

_$

(setq alist

(cons ‘(1 . 2) alist))

((1 . 2))

_$

(setq alist

(cons ‘(3 . 4) alist))

((3 . 4) (1 . 2))

_$ (setq alist

(cons ‘(5 . 6) alist))

((5 . 6) (3 . 4) (1 . 2))

Bu örnekte, alist değişkeni başlangıçta tanımsızdır ve dolayısıyla alist simgesinin değeri yoktur ve boştur. Bununla birlikte, boş “nil” değeri boş bir listeye eşit olduğu için, alist değişkeni cons  fonksiyonu için etkili bir değişkendir ve bu da eksenler işlevine argüman olarak aktarılabilen ve daha sonra setq fonksiyonu tarafından yeniden tanımlanan boş bir liste içerir.

İlişkilendirme Listesinden Bir Öğe Elde etme

Daha önce de gösterildiği gibi, blok adını elde ederken bir ilişkilendirme listesinden bir öğe edinmek için assoc fonksiyonunu kullanabilirsiniz:

_$

(assoc “Item 2” alist)

(“Item 2” . “Value 2“)

assoc fonksiyonu, anahtarı verilen anahtarla eşleşen ilişkilendirme listesindeki ilk öğeyi geri döndürür.

assoc fonksiyonu tarafından döndürülen madde göz önüne alındığında (bu örnekte eş çift) cdr fonksiyonunu kullanarak bu anahtarla ilişkili değeri elde edebiliriz:

_$

(cdr

(assoc “Item 2” alist))“Value 2”

İlişkilendirme Listesindeki Bir Öğenin Yerine Başka bir Öğe Koyma

Buraya kadar, her blok adını ve bloğun seçilen kısmıyla ilişkili miktarını kaydetmek için kullanılacak eş bir çiftin nasıl oluşturulacağını ve çeşitli eş çiftleri depolamak için kullanılacak bir ilişkilendirme listesinin nasıl inşa edileceğini gösterdik.

Son olarak, bir ilişkilendirme listesinde bir öğenin yerini alması (ve dolayısıyla güncelleştirilmesi) konusu anlaşılmalıdır, böylece ilişkilendirme listesindeki her blok adıyla ilişkilendirilen miktar, bloklar işlendikçe artırılır.

Bunun için subst  fonksiyonunu kullanacağız.

subst  fonksiyonu, belirli bir listede başka bir öğenin tüm tekrarları yerine bir (bir ilişkilendirme listesi olması gerekmeyen) öğeyi değiştirir:

 

_$ (subst 10 2 ‘(1 2 3 4 3 2 1))(1 10 3 4 3 10 1)

Bu nedenle, subst  fonksiyonu, eş çiftleri, mevcut eş çiftlerin yerine artan miktar değerleri ile ilişkilendirme listemizde ikame etmek için kullanabiliriz. Blok adları ilişkilendirme listesinde benzersiz olacağından, birden çok öğenin yerini alması konusunda endişelenmeye gerek yoktur.

_$ (subst ‘(“Block 3” . 2) ‘(“Block 3” . 1) ‘((“Block 1” . 1) (“Block 2” . 5) (“Block 3” . 1)))((“Block 1” . 1) (“Block 2” . 5) (“Block 3” . 2))

Blok Sayıcıyı Oluşturma

Şimdi, blok sayıcı programımıza dönelim –

Her bir bloğun oluşumlarını saymadan önce, blok sayı verilerini kaydedecek eş çiftleri ve ilişkilendirme listesini nasıl oluşturacağımızı gösterelim.

Bunu, yukarıda açıklanan yöntemleri kullanarak yapabilirsiniz:

(defun c:myblockcounter ( / blk idx lst sel ) ;Fonksiyonu tanımlama, yerel değişkenleri bildirme    (if ;Şayet aşağıdaki ifade boş olmayan “non nil” bir değer geri döndürürse,        (setq sel ;Aşağıdaki ifade tarafından döndürülen değeri ‘sel’ sembolüne ata.            (ssget ;Kullanıcıyı seçim yapması için uyar ve şayet seçim yapılırsa, seçim setini geri döndür.               ‘((0 . “INSERT”)) ;Seçimi sadece blok referansları için filitreleme (INSERTs)            ) ;ssget fonksiyonu sonu.        ) ;setq fonksiyonu sonu.        (repeat ;Parantezler arası ifadeyi aşağıdaki sayı kadar tekrarlama:            (setq idx ;Aşağıdaki ifade tarafından geri döndürülen değeri ‘idx’ sembolüne atama.                (sslength sel) ;Seçim setindeki öğe sayısını geri döndürme.         ) ;setq fonksiyonu sonu            (setq blk ;Blok isimlerini ‘blk’ değişkenine atama.                (cdr ;DXF grup 2 (blok ismi) ile ilişkili değeri elde etme.                    (assoc 2 ;Aşağıdaki DXF verilerinden DXF grup 2 eş çiftlerini elde etme.                        (entget ;Aşağıdaki varlık için, DXF veri listesini elde etme.                            (ssname sel ;Aşağıdaki endeks numarasındaki varlığı elde etme.                                (setq idx (1- idx)) ;(Seçim seti indeksi sıfırdan başladığı için) index değişkeninin değerini azaltma.                            ) ; ssname fonksiyonu sonu.                        ) ;entget fonksiyonu sonu.                    ) ;assoc fonksiyonu sonu.                ) ;cdr komutu sonu.            ) ;; end setq            (print blk) ;(test amaçlı olarak) blok ismini komut satırına yazdırma.        ) ;repeat fonksiyonu sonu.    ) ;if döngüsü sonu.    (princ) ;(if döngüsünün) son geri döndürdüğü ifadeyi engelleme.) ;defun fonksiyonu sonu.

Bu aşamada en önemli şey, lst  liste değişkenimizi fonksiyonumuzun yerel bir değişkeni olarak bildirmeyi unutmamaktır: c:myblockcounter – setq ifadesi, her yinelemeyle lst değişkenini yeniden tanımladığından, bu değişkenin değerinin döngü başlamadan önce boş olması önemlidir. Aksi takdirde veriler işlevin her kullanımı için bileşik kalırlar.

Yukarıdaki programı test ettikten sonra, aşağıdakine benzer bir çıktı alırız:

((“Block 1” . 1) (“Block 2” . 1) (“Block 1” . 1) (“Block 1” . 1) (“Block 2” . 1) (“Block 3” . 1))

Bu nedenle, her bir blok adı için eş çiftin nasıl oluşturulduğunu ve bu eş çiftleri içeren bir ilişkilendirme listesinin nasıl oluşturulacağını gösterdik.

Blok sayacı oluşturmak için, geriye yalnızca ilişkilendirme listenin anahtarının işlenmekte olan blok adıyla aynı olan bir eş çift içerdiğini test etmek ve varsa, ilişkili değeri artırmak, aksi takdirde yeni eş çifti ilişkilendirme listesine eklemek kalıyor.

Bunu başarmak için, yukarıda açıklandığı gibi assoc ve subst fonksiyonlarını kullanacağız:

Nihai Program

Şayet kodu yeniden biçimlendirir ve her satırdaki kod yorumlarını atlarsak, programımızın nihai hali aşağıdaki gibi olacaktır:

(defun c:myblockcounter ( / blk idx itm lst sel )

    (if (setq sel (ssget ‘((0 . “INSERT”))))

        (repeat (setq idx (sslength sel))

            (setq blk

(cdr

(assoc 2

(entget

(ssname sel

(setq idx (1– idx)))))))           

(if (setq itm (assoc blk lst))               

(setq lst (subst (cons blk (1+ (cdr itm))) itm lst))               

(setq lst (cons  (cons blk 1) lst))           

)       

)   

)   

(foreach itm lst (princ (strcat “\n” (car itm) “: “ (itoa (cdr itm)))))   

(princ)

)

Umarım bu makalemde anlattıklarımı okumaktan ve programı kendi başınıza yazmaktan keyif almışsınızdır!

Hakkında Sertan Türkan

AutoCAD Beyni

Bunu da Kontrol edin

Revitte Katman Sarma Hakkında

Kompozit duvar katmanları, duvarın ek yerlerinde ve uç başlarında sarılabilir. Duvarın uçlarına sarılacak bileşik duvar …

Bir cevap yazın

Yardıma mı ihtiyacınız var? Chat with us
Bir görüşme başlatmak için lütfen önce gizlilik politikamızı kabul edin.