AutoLISP

TEXT 2 3DSOLID

Dzisiaj krótko o szybkim modelowaniu prostych prymitywów brył w AutoCAD-zie… polegającym na konwersji wybranych tekstów na… trójwymiarowe bryły właśnie. Oczywiście teksty muszą spełniać pewne warunki, (ogólnie) opisujace geometrię brył (położenie i wielkość). Jest to proces odwrotny niż zwykle spotykany, czyli opiywanie właściwości obiektów.

Tekstowy „opis” bryły 3D w tym przypadku, pobierany jest z wybranego obiektu typu TEXT. Warstwa, położenie oraz obrót, są takie same jak dla tekstu, wartości geometrii (szerokość, wysokość i długość) określone są w wartości (treści) tekstu. Warunkiem koniecznym jest aby fragment tekstu zawierał (w jednym ciągu) trzy liczby rozdzielone dwoma znakami „x”. Teksty które nie spełniają tego warunku są pomijane.

Zdefiniowane jest polecenie TXT2SOL. Po wywołaniu należy wskazać teksty. Program sprawdza czy tekst spełnia warunki konieczne do utworzenia BOX-a, i (po ich spełnieniu) je tworzy. (Krótki) kod makra (w całości) wygląda tak:


; -------------------------------------------------------------------------------------- ;
; Convert TEXT to 3DSOLID by kojacek 2022                                                ;
; -------------------------------------------------------------------------------------- ;
(defun C:TXT2SOL ()(jk:SOL_Text->Box)(princ))
; -------------------------------------------------------------------------------------- ;
(defun jk:SOL_Text->Box (/ s CMD)
  (princ "\nConvert text to 3D Solid Box...")
  (if
    (setq s (jk:SOL_SGet-Text))
    (progn
      (setq CMD (getvar "CMDECHO"))
      (cd:SYS_UndoBegin)
      (setvar "CMDECHO" 0)
      (foreach % s (jk:SOL_3DBox-Data %))
      (setvar "CMDECHO" CMD)
      (cd:SYS_UndoEnd)
    )
    (princ "\nSelected objects are not correct.")
  )
)
; -------------------------------------------------------------------------------------- ;
(defun jk:SOL_3D-Text-p (Str / l s :a)
  (defun :a (i)
    (cd:STR_Parse
      (vl-list->string
        (mapcar
         '(lambda (%)
            (if
              (or
                (>= % 58)
                (<= % 47)
              ) 37 %
            )
          )
          (vl-string->list i)
        )
      ) "%" nil
    )
  )
  (if
    (wcmatch
      (setq s (strcase Str))
      "*#X#X#*,*#X##X#*,*#X###X#*,*#X####X#*"
    )
    (progn
      (setq l (cd:STR_Parse s "X" nil))
      (mapcar
        'read
        (list
          (last (:a (car l)))
          (cadr l)
          (car (:a (last l)))
        )
      )
    )
  )
)
; -------------------------------------------------------------------------------------- ;
(defun jk:SOL_SGet-Text (/ s l)
  (if
    (setq s
      (ssget
        (list
          (cons 0 "TEXT")
          (cons 410 (getvar "CTAB"))
        )
      )
    )
    (setq l (cd:SSX_Convert s 0)
          l (vl-remove-if
              'numberp
              (mapcar
               '(lambda (%)
                 (if
                   (jk:SOL_3D-Text-p
                     (cdr (assoc 1 (entget %)))
                   ) % 0
                  )
                ) l
              )
            )
    )
  )
)
; -------------------------------------------------------------------------------------- ;
(defun jk:SOL_3DBox-Data (Ent / d b x c o e)
  (setq d (entget Ent)
        x (jk:SOL_3D-Text-p (cdr (assoc 1 d)))
        b (acet-geom-textbox d 0)
        c (acet-geom-midpoint (car b)(caddr b))
        e (entlast)
  )
  (command "_BOX" "_c" c "_l" (caddr x)(cadr x)(car x))
  (setq o (entlast))
  (if
    (/= o e)
    (progn
      (setq v (vlax-ename->vla-object o))
      (vla-rotate v
        (vlax-3d-point c)(cdr (assoc 50 d))
      )
      (vla-put-Layer v (cdr (assoc 8 d)))
    )
  )
)
; -------------------------------------------------------------------------------------- ;
(princ)

Rzecz jasna konieczne jest załadowanie CADPL-Pack-a. Potrzebne jest również wcześniejsze wczytanie pakietu ExpressTools AutoCAD-a (wykorzystywane są dwie funkcje acet-). „Sprytne” umieszczenie tekstów, pozwala na szybkie tworzenie brył, z jednoczesnym precyzyjnym położeniem elementów. Jakiś szybki glulam portal frame? Voila:

Zautomatyzowany sposób opisywania brył 3D (typu box) omawiałem we wpisie Zliczanie 3DSOLID. Natomiast ogólnie o prymitywach brył w AutoCAD-zie (typu box), słów kilka można znaleźć tutaj: AutoCAD 3D.

To jest #213 wpis na blogu

( . . . )

AutoCAD, AutoLISP

DWGPROPS

Polecenie DWGPROPS (DWGWŁAŚCIWOŚCI) ustawia i wyświetla właściwości pliku aktualnego rysunku. Wyświetla okno dialogowe z czterema zakładkami, z których jednej – o nazwie [Niestandardowe] – poświęcę wiecej uwagi.

Karta [Ogólne] zawiera wszystkie dane systemowe dotyczace pliku, takie jak typ, nazwa, lokalizacja, dane dotyczące zapisu/dostępu, czy atrybuty pliku. Tych danych nie można samodzielnie modyfikować. W karcie [Podsumowanie] można uzupełnić pewne typowe dane, takie jak: tytuł, temat, czy słowa kluczowe. Dane te mogą być pomocne podczas przeszukiwania archiwum plików. Karta [Statystyka] (tylko do odczytu) zawiera pewne dane statystyczne dotyczące pliku (nazwę autora, czas edycji, wersję). Wreszcie, ostatnia (najbardziej nas interesująca) karta – [Niestandardowe]…

Pomysłów na wykorzystanie tych danych jest kilka – przedstawię dwa, z których (czasem) korzystam.

  1. Miejsce zapisu ustawień aplikacji. Dane w DWGPROPS wydają się być idealnym miejscem na przechowywanie pewnych ustawień aplikacji (np. LISP). Pozwalają bowiem użytkownikowi na modyfikację tych danych, bez konieczności tworzenia specjalnego interfejsu zmiany ustawień. Przykładem takiego zastosowania jest przedstawiony tutaj program (zarówno w wersji 1 jak i 2). Dwa parametry ustawień programu, których początkowe wartości, ustala się w trakcie działania programu, zapisywane są we niestandardowych właściwościach pliku: Wartość o nazwie UWG, odpowiada za ustalenie 5, 6, 7 albo 8 strefy ukłdu współrzędnych geograficznych (zobacz). Drugi zaś o nazwie DEC, odpowiada za ilość miejsc dziesiętnych zapisu współrzędnych, jeśli zapisywane są jako wartości liczbowe (to wersja 2 programu). Rzecz jasna oprogramowanie musi zapewnić kontrolę poprawności tych danych.
  2. Przechowywanie danych tekstowych wspólnych dla projektu składającego się z wielu plików.  Są to informacje zwykle występujące w tabliczkach rysunkowych (w arkuszach), a zawierające powtarzalne, wspólne dla wielu plików dane. Ten sposób jest łatwy do modyfikacji, aktualizacji i stosunkowo szybki w użyciu. Pomysłem na takie zastosowanie jest, w pierwszej kolejności użycie pliku tekstowego (np. standardowego pliku ini). Dane w nim się znajdujace mogą być teraz wczytane kolejno (a) do DWGPROPS: a następnie (b) do bloków tabliczek rysunkowych, jako zwykłe wartości atrybutów: albo (bardziej elastyczny sposób), jako pola danych (czyli obiekty typu FIELD): Ten sposób pozwala na samoaktualizację danych w tabliczkch rysynkowych (czy też innych blokach), po każdorazowej zmianie danych w DWGPROPS. Zmiany te mogą być wprowadzane ręcznie, lub w sposób automatyczny przez oprogramowanie.

Oczywiście sposobów na sprytne wykorzystywanie danych DWGPROPS, może być więcej, zwłaszcza że, mogą być to informacje bardzo zindywidualizowane – przedstawiłem na prostych przykładach jedynie zarys możliwości. „Wytrawni” programiści mogą pokusić się o stworzenie narzędzi, zapisujących, odczytujacych, aktualizujacych, usuwających, dowolne tekstowe dane w DWGPROPS, dla wielu różnych zastosowań, pojedyńczo czy też masowo dla wielu plików.

Omawiając DWGPROPS, wspomnę jeszcze o dwóch rzeczch: dane te mogą być przetwarzane przez standardowe polecenie AutoCAD-a do wyodrębniania danych (DATAEXTRACTION), jak też istnieje polecenie z ExpressTool, o nazwie PROPULATE pozwalające w pewien (ale dość ograniczony) sposób manipulować tymi danymi.

Na koniec – sprawdźmy „pojemność” niestandardowych danych w DWGPROPS. Poniższy kod (wykorzystujący funkcje z CADPL-Pack‚a):dodaje 1000 nowych wpisów:

(  .  .  . )

To jest 199 wpis (czwarty w tym roku).

AutoCAD, AutoLISP

FLATTEN inaczej

Małe co nieco o wypłaszczaniu – czyli FLATTEN inaczej. (LISP-owe) narzędzie o tej nazwie z dodatkowej skrzynki (Express Tool), zna chyba każdy użytkownik AutoCAD-a:

Na swoje potrzeby, napisałem (LISP-em rzecz jasna) nieco inne narzędzie służące „wypłaszczaniu” obiektów. Działanie tegoż widać poniżej:

Zasadnicze różnice z AutoCAD-owym FLATTEN to:

  • edycja wybranych obiektów, a nie tworzenie ich kopii
  • ograniczona lista edytowanych obiektów (np. standardowo wykluczenie brył, polilinii i powierzchni 3D)
  • możliwość określenia dowolnego docelowego poziomu obiektów (choć poziom 0,00 jest poziomem domyślnym)
  • możliwość działania (co jest istotne) w edytorze bloków:

  • szybsze działanie

Jak to widać na powyższych animacjach, wyraźnie widać inne docelowe różnice – o ile FLATTEN ma na celu stworzenie dwuwymiarowej reprzezentacji obiektów 3D, to mój program służy bardziej do ustalenia jednego poziomu obiektów znajdujących się w różnych miejscach przestrzeni 3D. W skrócie do „naprawy” położenia, czasem niedoskonałych (z różnych powodów) obiektów w rysunku. Ręczna edycja takich obiektów jest zwykle czasochłonna, a program załatwia takie działania w ułamku sekundy. Czas poświęcony na napisanie programu, w praktyce, (o czym staram się zawsze tutaj mówić) nie jest czasem straconym.

[Edycja 18-10-2020] :: Program w najnowszej wersji opisałem: TUTAJ

 .  .  .  )

To jest #192 wpis…

 

AutoCAD

Obrazy a RTEXT

RTEXT czyli obiekty tekstu zdalnego, (albo także zwanego) reaktywnego, tworzą odniesienia do zewnętrznego pliku tekstowego, albo też wyświetlają (aktualną) wartość wyrażenia języka DIESEL. Pozwalają w ten sposób na tworzenie dynamicznie zmieniającego się tekstu w obszrze rysunku AutoCAD-a. Przykładowo: pewne (stałe) uwagi odnoszące się do każdego arkusza w rysunku, mogą być odniesieniami do pliku tekstowego, a wizualizowane w rysunku jako tekst. Każdorazowa zmiana zawartości pliku, skutkuje zmianą uwag znajdujących się w rysunku. To samo dotyczy wyrażeń języka DIESEL. W ten sposób tworzona jest (animacja poniżej) tekstowa reprezentacja nazw wszystkich istniejących odniesień obrazów graficznych (obiekty IMAGE) w rysunku:

Większość opracowań geodezyjnych (lub innych bazujących na mapach) wymaga wczytania skanów tradycyjnej mapy, w celu naniesienia dowolnych instalacji czy też digitalizacji mapy. Stworzenie rzeczywistej listy wczytanych plików, może wydawać się zadaniem trudnym, jednak wykorzystując w pełni możliwości oferowane przez AutoCAD-a, może być w efekcie banalnym zadaniem…

Jedną z możliwości wykorzystania wyświetlania wyrażenia języka DIESEL jest użycie funkcji images. Tworzy ona listę obrazó dołaczonych do rysunku, Składnia tej funkcji wygląda tak:
$(images [, flags [, leader [, text]]])
gdzie:

  • wartość argumentu [flags] ma wartość: 4 = nie wyświetlaj nazwy pliku, 8 = nie wyświetlaj ścieżki.
  • wartość argumentu [leader] to tekst wstawiany przed każdym IMAGE
  • wartość argumentu text jest tekstem dołączanym do każdego wpisu (bez ostatniego)

Podobnie można tworzyć listę odnośników zewnętrznych (XRef). Dodatkowo trzeba dodać, że obiekty RTEXT można rozbić używając polecenia ROZBIJ (_EXPLODE), konwertując zawartość tekstu do obiektu tekstu wielowierszowego MTEXT. Rzecz jasna w ten sposób zostanie przerwana dynamika obiektu RTEXT, a powstaje jedynie graficzna reprezentacja zawartości tekstowej obiektu.

O obiektach RTEXT wspominałem już we wpisie Teksty i opisy.

To jest 180 wpis na blogu…

.  .  .  )

AutoLISP

ARX load

ObjectARX ® (AutoCAD Runtime Extension) jest środowiskiem programowania służącym do tworzenia programów i aplikacji dla AutoCAD-a. Programy generowane są w języku kompilowanym i działają w tej samej przestrzeni adresowej co AutoCAD. Umożliwia to im bezpośredni dostęp do struktur baz danych, systemu graficznego oraz mechanizmów geometrii, tak samo jak robi to program AutoCAD. Pliki aplikacji mają rozszerzenie arx lub (od wersji AutoCAD 2014) także crx.

Z LISP-owego punktu widzenia, użyteczność programów ARX wynika z możliwości wykorzystania poleceń zdefiniowanych w aplikacji, oraz – w szczególnych przypadkach z dostępu do funkcji LISP-a w nich definiowanych. Typowymi przykładami może być funkcja cal (definiowana w module kalkulatora geometrycznego AutoCAD-a), biblioteka acetutil.arx z funkcjami definiowanymi w pakiecie Express Tool, czy (niezleżna) biblioteka DOSLib.

Korzystanie (przez LISP-a) z tych dobrodziejstw możliwe jest po wcześniejszym załadowaniu pliku biblioteki arx. Niestety AutoLISP nie robi tego automatycznie, i na programującym spoczywa obowiązek sprawdzenia czy możliwe jest wywołanie funkcji (lub polecenia), oraz w razie konieczności załadowanie odpowiedniego pliku. Często spotykanym błędem jest pominięcie tego procesu, w wyniku czego (cyt.) „program raz działa, a czasem wywala błąd… „. 

Dla obsługi aplikacji arx AutoLISP oferuje funkcje:

  • arx – zwraca listę aktualnie wczytanych (czyli dostępnych) plików bibliotek arx (bez ścieżek dostępu)
  • arxload – wczytuje (jeśli to możliwe) plik aplikacji arx.
  • arxunload – usuwa z pamięci (wczytany i dostępny) plik aplikacji arx.
  • vl-arx-import – pozwala załadować wybrane (lub wszystkie) funkcje zdefiniowane w pliku arx, dla programu lispowego VLX.

Ważne – ponieważ AutoCAD może korzystać zarówno z plików typu arx jak też crx, w wywołaniu funkcji arx można nie podawać rozszerzenia pliku. Przykładowo – standardowy kalkulator geometryczny AutoCAD-a, plik geomcal.arx, od wersji 2014 jest dostarczany jako plik geomcal.crx. Starsze programy AutoLISP mogą w kodzie zawierać, jawne odwołanie do rozszerzenia pliku (arx) i z tego powodu próba załadowania kalkulatora, może się nie udać:

Poniższa animacja ilustruje przykład próby załadowania aplikacji geomcal.arx (AutoCAD 2013 i wersje niższe) lub geomcal.crx (w AutoCAD-zie wyżym niż wersja 2014), bez konieczności sprawdzania typu rozszerzenia aplikacji.

Co ciekawe – funkcja arxunload, nie działa tak samo, dla usunięcia z pamięci apliacji arx, trzeba podać rozszerzenie pliku, i najważniejsze – plików crx nie można „wyładować”, możliwe jest to tylko dla plików arx. Warto o tym pamiętać.

 

(   .  .  .  )

 

AutoLISP

DBCOUNT – zliczanie bloków dynamicznych

Użytkownicy AutoCAD-a, z zainstalowanym Express Tool, z pewnością znają narzędzie o nazwie BCOUNT.  To sprytne narzędzie, jeśli dobrze pamiętam, znajduje się e ET chyba od samego początku. Nie rozpisując się – BCOUNT służy do:

Mimo swoich niezaprzeczalnych zalet BCOUNT, ma niestety pewną dość istotną przypadłość. Mianowicie – nie potrafi zliczyć wystąpień bloków dynamicznych. Bazuje bowiem tylko na nazwie bloku (właściwość Name), ignorując zupełnie cechę bloków dynamicznych, czyli nazwę efektywną (właściwość EffectiveName). Opisywałem to już TUTAJ.

W różnego rodzaju schematach, rysunkach złożeniowych, zestawieniach, gdzie precyzyjne określenie ilości wystąpień bloków (także dynamicznych) ma istotne znaczenie, niedogodność ta jest bardzo uciążliwa. Oczywiście z pomocą przychodzi LISP, który w magiczny sposób za pośrednictwem swych nawiasów potrafi czynić życie lepszym 😉 … W ten sposób powstało narzędzie o nazwie DBC. Działanie polecenia widać poniżej:

Wyboru bloku dokonuje się na dwa sposoby, które należy określić po wywołaniu polecenia. Pierwszy – przez wskazanie bloku, lub drugi – wybranie nazwy bloku z listy w oknie dialogowym. Wystąpienia określonego bloku mogą zostać następnie policzone albo dla utworzonego wyboru (wskazania), albo dla wszystkich w aktualnym obszarze, albo dla wszystkich w rysunku. Te opcje też określa się w linii poleceń. Dla każdego wyboru polecenie kończy się informacją o ilości wystąpień bloku.

Program wymaga załadowania biblioteki CADPL-Pack. Kod całości wygląda tak:


; ==================================================================== ;
; DynBlkCount.lsp by kojacek 2015/2017                                 ;
;                                                                      ;
; Polecenie DBC zlicza ilosc wystapien blokow dynamicznych             ;
;                                                                      ;
; ==================================================================== ;
(defun C:DBC (/ a s x _Sel _Dlg _Get)
  (defun _Sel (/ s d r)
    (if
      (not (setq s (car (entsel "\nWskaż blok dynamiczny: "))))
      (princ "\nNic nie wskazano. ")
      (if
        (not (= "INSERT" (cdr (assoc 0 (setq d (entget s))))))
        (princ "\nNie wskazano bloku. ")
        (if
          (zerop (getpropertyvalue s "IsDynamicBlock"))
          (princ "\nTo nie jest blok dynamiczny. ")
          (setq r (getpropertyvalue s "BlockTableRecord/Name"))
        )
      )
    ) r
  )
  (defun _Dlg (/ l r)
    (if
      (setq l (cd:BLK_GetDynBlockList))
      (if
        (setq d
          (cd:DCL_StdListDialog
            l 0
            "Zlicz bloki dynamiczne" "Wybierz blok:"
            30
            20
            2
            12
            (list "&OK" "&Anuluj")
            nil T T nil
          )
        )
        (setq r (nth d l))
        (princ "\nNic nie wybrano. ")
      )
      (princ "\nW rysunku nie ma bloków dynamicznych. ")
    )
  )
  (defun _Get (n / u f r i v)
    (setq f
      (if
        (= 1 (length (setq u (cd:BLK_GetDynBlockNames n))))
        (car u)
        (cd:STR_ReParse u ",`")
      )
          i (list (cons 0 "INSERT")(cons 2 f))
    )
    (if
      (setq r
        (cd:USR_GetKeyWord
          (strcat "\nBlok \"" (strcase n) "\"")
          '("Wybierz" "Aktualny obszar" "Cały rysunek" "Koniec")
          "Wybierz"
        )
      )
      (cond
        ( (= r "Wybierz")(setq v (ssget i)))
        ( (= r "Aktualny")
          (setq v
            (ssget "_x"
              (append i
                (list (cons 410 (getvar "CTAB")))
              )
            )
          )
        )
        ( (= r "Cały")(setq v (ssget "_x" i)))
        (t (princ "\nAnulowano. "))
      )
    ) v
  )
; -------------------------------------------------------------------- ; 
  (if
    (setq a
      (cd:USR_GetKeyWord
        "\nZlicz bloki dynamiczne"
        '("Wskaż" "Lista" "Koniec")
        "Wskaż"
      )
    )
    (progn
      (cond
        ( (= a "Wskaż")(if (setq s (_Sel))(setq x (_Get s))))
        ( (= a "Lista")(if (setq s (_Dlg))(setq x (_Get s))))
        (t (princ "\nAnulowano. "))
      )
      (if x
        (princ
          (strcat "\nZnaleziono: " (itoa (sslength x)) " bloków. ")
        )
      )
    )
    (princ "\nAnulowano. ")
  )
  (princ)
)
; -------------------------------------------------------------------- ;
(princ)

( . . . )

AutoLISP

AutoLISP i pliki *.ini

Dzisiaj parę słów o plikach *.ini, i możliwościach manipulowania nimi za pomocą AutoLISP-a. Pliki o rozszerzeniu ini, to zwykłe pliki tekstowe, zawierające dane sformatowane w uporządkowany sposób. Wykorzystywane są jako pliki inicjalizacyjne i konfiguracyjne, w wielu programach systemu Windows. To stosunkowo przestarzały sposób, niemniej nadal szeroko wykorzystywany, ze względu na swoją prostotę, przejrzystość i elastyczność. Możliwość edycji pliku zarówno przez specjalizowany program, jak również przez użytkownika (w zwyczajnym edytorze tekstowym), uważana jest za zaletę. Głównymi wadami przechowywania danych w ten sposób są: ograniczenie typów danych (to tylko plik tekstowy), brak możliwości zagnieżdżenia danych i (co wyżej wymieniłem jako zaletę) – zbyt łatwy dostęp. Struktura pliku ini jest następująca:

  • dane pogrupowane są w unikalne sekcje, których nazwa umieszczona jest pomiędzy kwadratowymi nawiasami.
  • w każdej sekcji w kolejnych liniach dane są sformatowane jako asocjacje rozpoznawane przez klucz (unikalny w sekcji), po którym występuje separator (znak równości), a następnie właściwa wartość.
  • znak średnika na początku linii oznacza komentarz i jego treść jest ignorowana (tak jak w LISP-ie)

Poniżej przykład zawartości pliku has.ini, który z powodzeniem stosuję do zapisywania ustawień programu has.lsp:

Krótki program has.lsp, wykorzystujący ustawienia właśnie w pliku ini,postaram się przedstawić w bliskiej przyszłości, teraz omówię sposoby manipulacji danymi przechowywanymi w plikach *.ini, za pomocą AutoLISP-a, z których on korzysta.

Ani sam AutoLISP, ani VisualLISP nie oferują żadnych bezpośrednich funkcji dostępu do plików typu ini. Oczywiście można napisać własne funkcje tego typu, bazując na mechanizmach zapisu i odczytu plików tekstowych, jakie oferuje LISP. Istnieją jednak jeszcze dwie drogi: wykorzystanie biblioteki acetutil.arx, z pakietu ExpressTools, lub narzędzia firm trzecich – na przykład DOSLib (funkcje dos_getini i dos_getini). W swojej praktyce z reguły korzystam z tej pierwszej możliwości – zawsze bowiem, w każdej wersji AutoCAD-a instaluję ET.

W acetutil.arx zostały zdefiniowane dwie funkcje dostępu do plików *.ini. Są to:

  • acet-ini-get – służąca do odczytu. Jej składnia wygląda tak:
    (acet-ini-get inifile [section [key [default]]])

    gdzie wymaganym argumentem jest inifile – nazwa pliku do odczytu, oraz opcjonalne argumenty section, key i default. Jeśli występuje tylko argument inifile, ta funkcja zwraca listę nazw sekcji lub nil w przypadku gdy nie można otworzyć pliku ini do odczytu. Jeżeli występuje argument z nazwą sekcji (section), zostanie zwrócona lista nazw kluczy w tej sekcji. Jeżeli argumentem jest key, zwracana jest wartość zeń skojarzona. Argument default (jeśli występuje) zwracany jest w przypadku gdy nie można znaleźć wartości podanej w argumencie key. Funkcja zwraca nil, jeśli nie można znaleźć żadnych informacji.

  • acet-ini-set – służąca do zapisu. Jej składnia wygląda tak:
    (acet-ini-set inifile section [key [value]])

    gdzie dwa wymagane argumenty to oczywiście  inifile – nazwa pliku, oraz section. Kolejne (key i value) są argumentami opcjonalnymi. Jeżeli zostanie podany argument section z nieistniejącym wpisem w pliku (i równocześnie podane zostaną argumenty key i value), zostanie on utworzony, wraz z kluczem i przypisaną wartością . Wywołanie funkcji tylko z argumentem section (istniejącym w pliku), zostanie wtedy usunięta cała sekcja (łącznie ze wszystkimi wpisami w sekcji). Argument value zawsze nadpisuje znalezioną w pliku wartość klucza key.

Stosując tylko te dwie funkcje mamy możliwość pełnej kontroli nad ustawieniami zapisywanymi i odczytywanymi w dowolnym pliku ini. Oczywiście pamiętać należy o ograniczeniach, także wcześniej wspomnianych. Ponadto należy zwracać uwagę na używanie w nazwach czy wartościach małych i wielkich liter.

Alternatywnym sposobem zapisywania ustawień programów jest wykorzystywanie dostępu do rejestru Windows. Niemniej jednak stosowanie plików ini, w wielu przypadkach jest ze względu na swoją prostotę i elastyczność rozwiązaniem najbardziej optymalnym.

(  . . . )

AutoCAD, Excel

ATTOUT ATTIN czyli znów o atrybutach

Kolejny raz o atrybutach bloków. Ich eksporcie i imporcie. Wcześniej o eksporcie wartości atrybutów już pisałem tutaj: ATRWYC – Wyciąg danych z atrybutów bloku, teraz krótko opiszę możliwości szybkiej i masowej edycji wartości atrybutów bloków za pomocą poleceń ATTOUT i ATTIN, z pakietu Express Tools.

Jako praktyczny przykład posłuży nam taka sytuacja – w istniejącym rysunku budowlanym potrzebujemy rozszerzyć informacje w „metryczkach pomieszczeń”, o pewne dane, niech tutaj będą to: funkcja pomieszczenia, jego wysokość, oraz wykończenie posadzki.

et-att-01

Blok będący etykietą pomieszczenia, ma tylko dwa atrybuty – numer pomieszczenia i jego powierzchnia. Powierzchnia przypisana jest dynamicznie jaki FIELD i jest automatycznie aktualizowana w przypadku zmiany obwiedni pomieszczenia. Taki mechanizm opisywałem tutaj: Powierzchnie.

et-att-02

Ponieważ ręczna zamiana bloku „metryczki pomieszczenia” nie wchodzi w grę, wybieramy drogę redefinicji istniejącego bloku. Pamiętamy tylko żeby nie zmieniać istniejących definicji atrybutów – w edytorze bloku dodajemy tylko nowe.

et-att-03

Tutaj będą to trzy nowe atrybuty o tagach H=, F= i G=. Nie mają żadnych wartości domyślnych, i są ustawione na niedrukowalnej warstwie DefPoints, a dla wyróżnienia z innym kolorem, niż pozostałe:

et-att-04

Po skończonej edycji bloku, zapisaniu zmian, przychodzi kolej na aktualizację rysunku. Ponieważ jak wiadomo zmiany definicji bloków są automatycznie aktualizowane tylko dla graficznych elementów rysunkowych, a dla definicji atrybutów tylko dla nowych wstawień, wprowadzone zmiany w bloku nie są widoczne. Z pomocą przychodzi polecenie ATRSYN (_ATTSYNC), czyli synchronizacja atrybutów. Po wywołaniu polecenia wystarczy wskazać blok i potwierdzić działanie:

et-att-19

Po zakończeniu synchronizacji wszystkie wstawienia bloku w rysunku powinny zostać zaktualizowane, o nowe atrybuty zgodnie ze zmianami w definicji bloku.

Czas teraz na wyeksportowanie danych z AutoCAD-a, do programu zewnętrznego – w naszym przypadku do Excel-a, przez plik tekstowy. Najpierw wybierzmy wszystkie bloki których dane chcemy pobrać. Możemy to zrobić na kilka sposobów – najszybciej, jako wytrawni znawcy pisma nawiasowego, wpisujemy po prostu:

et-att-07

Następnie w linii poleceń, albo z menu / wstążki wybieramy polecenie ATTIN:

et-att-06

Wystarczy teraz podać nazwę i lokalizację (domyślnie katalog rysunku) pliku tekstowego do którego zostaną wyeksportowane dane. Na zgłoszenie wyboru obiektów podajemy opcję E oznaczający poprzEdni (_prEvious) zbiór wskazań:

et-att-10

Jak widać wybranych i wyeksportowanych zostało 81 danych bloków. Teraz kolej na Excela. Z menu [Plik], wybieramy pobieranie danych z zewnętrznych, wskazując źródło [Z tekstu], a następnie wskazujemy nasz plik tekstowy:

et-att-09

Uruchamia się sprytny kreator importu – trzeba przyznać że Excel bardzo dobrze sobie radzi przy imporcie plików tekstowych, nie ma żadnych problemów z rozpoznawaniem sposobu formatowania danych:

et-att-11

W kolejnych krokach nie mamy właściwie nic do zrobienia, wystarczy tylko śledzić czy proponowane wartości domyślne, są poprawne, w razie konieczności zmieniamy ustawienia:

et-att-12

W podglądzie okna dialogowego, na bieżąco można kontrolować cały proces wczytywania danych, zmienić typ danych dla każdej kolumny itp. W większości przypadków format danych Ogólny jest wystarczający:

et-att-13

Na koniec pozostaje wskazać miejsce w arkuszu, gdzie dane zostaną umieszczone:

et-att-14

… i cały proces wczytywania danych mamy za sobą. Jak widać dane dla każdego bloku są umieszczone w jednym wierszu (rekordzie), pierwszy wiersz to nagłówki danych:

et-att-15

Teraz wystarczy dane w arkuszu odpowiednio uzupełnić. Pamiętać należy że nie zmieniamy dwóch pierwszych kolumn. Pierwszy to uchwyt (handle) obiektu, a drugi to nazwa bloku, te dane są potrzebne do identyfikacji elementu rysunkowego. O uchwytach obiektów pisałem przy okazji funkcji handent. W tym przykładzie nie zmieniamy też kolumny AREA, jest to bowiem powierzchnia związana FIELD-em, a tych danych nie chcemy zmieniać ani tracić. Tu edycji podlegać będą informacje do zapisu w atrybutach o tagach H=, F=, i G=. Wiedzieć trzeba że nie wszystkie dane musimy tu wypełniać – puste komórki, nie zostaną po prostu wczytywane jako wartości atrybutów.

et-att-16

Teraz trzeba plik zapisać – ważne – nadal jako plik tekstowy. Wprawdzie Excel, będzie nam sugerował zapis w jego formacie, konsekwentnie decydujemy że ma to być plik o rozszerzeniu txt. W tym miejscu możemy zamknąć Excela i wrócić do AutoCAD-a.

Tu zaś (po powrocie) czeka nas wczytanie z powrotem (zmienionych już) danych. Podobnie jak miało to miejsce przy eksporcie, skorzystamy z polecenia Express Tools, o nazwie ATTIN.

et-att-17

Po wybraniu pliku tekstowego do wczytania, w ułamku sekundy wszystkie wartości atrybutów interesujących nas bloków zostały zaktualizowane:

et-att-18

Właściwie to już wszystko, przedstawiony tutaj prosty przykład, procesu zmiany definicji bloku / eksportu / zmiany / importu danych, miał na celu pokazanie jak szybko, wydajnie i bezbłędnie można pracować, wykorzystując stosunkowo proste narzędzia. Nie wyczerpuje on wszystkich możliwości, z jakich można korzystać. Polecenia ATTIN i ATTOUT mogą pomagać w wielu innych zadaniach, na styku model CAD / dane zewnętrzne.  Niewątpliwe dobrze przemyślana organizacja rysunku, stosowanie bloków, atrybutów, ustalenie standardów i ich przestrzeganie, będą tutaj znaczącym ułatwieniem.

AutoCAD, AutoLISP

Standardy – Style tekstu

Wszystkie obiekty tekstowe AutoCAD-a, muszą mieć przypisany nazwany styl tekstu. Domyślnym i nieusuwalnym stylem jest styl o nazwie STANDARD. Style tekstu są obiektami niegraficznymi (typu TABLE) podobnie jak warstwy czy rodzaje linii. Definicje stylów tekstu określają takie właściwości jak czcionka, wysokość, kierunek, kąt pochylenia itp. AutoCAD obsługuje dwa rodzaje czcionek:

  • SHX – czcionki wektorowe AutoCAD-a,
  • TTF – (TrueTypeFont) systemowe czcionki Windows.

Do tworzenia modyfikowania i określania jako aktualny styl tekstu, służy polecenie STYL (_STYLE). W oknie dialogowym dokonuje się wszystkich ustawień dotyczących stylu tekstu:

tss_styledlg

Na swój użytek, mając na celu standaryzację ustawień korzystam z programu lispowego, który napisałem już jakiś czas temu, służącego do uproszczonego i szybkiego tworzenia stylów tekstu. Są one generowane na podstawie zapisów w pliku konfiguracyjnym tylu ini. Zawierają tylko podstawowe dane – z reguły nie używam tekstów o wyszukanych cechach (odwrócone, wstecz, wieloznaki (np. chiński BigFont) itp.). Ostatnio program został przeformatowany tak aby korzystał z CADPL-Pack‚a. Program obejmuje dwa pliki: TextStyleStd.lsp i TextStyleStd.ini, które muszą być w jednym katalogu, i muszą znajdować się w bibliotecznej ścieżce poszukiwań AutoCAD-a. Okno dialogowe (plik dcl) jest tworzone w sposób dynamiczny. Zdefiniowane jest polecenie TSS, które wywołuje okno dialogowe:

tss_dlg

W oknie można z listy, wybrać styl tekstu spośród wszystkich zdefiniowanych w pliku TextStyleStd.ini. Przycisk [Wczytaj] służy do utworzenia nowego stylu tekstu. Jeśli styl o tej samej nazwie jest już zdefiniowany w rysunku, przycisk jest nieaktywny:

tss_dlg2

Plik TextStyleStd.ini zawierający definicje stylu tekstu ma bardzo prostą konstrukcję. Zapewnia utrzymanie standardów, przenośność, oraz dużą elastyczność i uniwersalność. W przeciwieństwie np. do plików prototypowych, pozwala na tworzenie stylów tylko na żądanie. Pozwala to na większą kontrolę używanych stylów. Plik można dowolnie edytować w zwyczajnym edytorze tekstowym. Wygląda (fragment) tak:

tss_ini

Edycji mogą podlegać tylko grupy (nazwy w nawiasach) z wyłączeniem grupy [General]. Każda grupa jest nazwą stylu tekstu – wyświetlaną w oknie dialogowym. Definicje obejmują tylko cztery pozycje. Są to:

  • FontFile – nazwa pliku czcionki. Jeżeli jest standardową czcionką AutoCAD-a, lub Windows, nazwa jest krótka. Jeśli plik czcionki znajduje się w innym miejscu należy podać całą ścieżkę.  Nie korzystam z tej możliwości – moje style używają czcionek ze standardowych lokalizacji AutoCAD-a i Windows.
  • Height – wysokość tekstu. Ustalenie wysokości większej od 0.0 powoduje automatyczne ustawienie wysokości tekstu dla stylu. Wartość 0.0, określa wysokość tekstu będzie równej ostatniej używanej wysokości tekstu lub wartości zapisanej w pliku szablonu rysunku. Ze względu na elastyczność stosuję zawsze wysokość 0.0.
  • Width – wielkość współczynnika szerokości fontu. Pozwala kontrolować kondensację fontu. Stosuję tylko dla fontów SHX, zwykle dla „ściśnięcia” tekstu.
  • ObliqueAngle – kąt pochylenia tekstu. Wprowadzenie wartości z przedziału od -85 do 85 powoduje pochylenie tekstu, zaś 0.0 oznacza czcionkę prostą. Wartość liczona jest od pionowej orientacji liter – oznacza to że pochylenie 75 stopni, wymaga podania w pliku ini, wartości 15.0. Stosuję tylko do SHX (dla TTF wybieram predefiniowany font typu Italic.

Ustawienia tych czterech pozycji wystarcza do szybkiego ustalenia stylu tekst przez program TextStyleStd.lsp

Polecenie: TSS       Pobierz: tss.zip
Program działa we wszystkich wersjach AutoCAD-a, począwszy od wersji 2000. Wymaga zainstalowanego ExpressTools, oraz (oczywiście) załadowania CADPL-Pack’a.

AutoLISP

Polilinia zamknięta

Jak wiadomo polilinia może być otwarta lub zamknięta. O ile pierwszy przypadek nie budzi żadnych wątpliwości, to drugi może stwarzać czasem problemy. Chodzi o czasem spotykany przypadek polilinii która jest wprawdzie zamknięta, ale jej punkty pierwszy i ostatni się pokrywają. Takie elementy spotkałem kiedyś po zaimportowaniu pliku wymiany DXF. Okazały się być uciążliwe w automatyzacji, bowiem poprzez swoją „zakłamaną” budowę utrudniały wybór i edycję elementów (obiekt graficznie wyglądał jak czworokąt, w rzeczywistości miał pięć segmentów – ostatni o zerowej długości). Strukturę DXF takich polilinii (wyglądających identycznie trójkątów) ilustruje poniższy obraz:lwplines

Poniżej dwie funkcje które pozwalają nieco ujarzmić tego rodzaju polilinie. Pierwsza sprawdza, czy pierwszy i ostatni punkt polilinii, mają takie same współrzędne. Druga dla Ename takiej polilinii, usuwa ostatni zerowy segment. Argument Closed określa czy funkcja ma zamknąć polilinię w wypadku jeśli była otwarta.

; =============================================================== ;
; Zwraca T jesli pokrywaja sie 1 i ostatni wierzcholek LWPolyline ;
; =============================================================== ;
(defun jk:LWP_EqualStartEnd-p (Ename / p)
   (setq p (cd:DXF_Massoc 10 (entget Ename)))
   (zerop (distance (car p)(last p)))
)
; =============================================================== ;
; Usuwa ostatni wierzcholek LWPoly jesli pokrywa sie z pierwszym ;
; gdy argument Closed funkcja zamyka obiekt (gdy jest otwarty) ;
; Zwraca T / nil ;
; =============================================================== ;
(defun jk:LWP_CorrectStartEndPoint (Ename Closed / d h l)
  (if
    (jk:LWP_EqualStartEnd-p Ename)
    (progn
      (setq d (entget Ename)
            l (length d)
            h (cdr (assoc 210 d))
      )
      (setq d (reverse d))
      (while
        (/= (caar d) 10)
        (setq d (cdr d))
      )
      (setq d (reverse (cdr d)))
      (entmod (append d (list (cons 210 h))))
      (if
        (and
           Closed
           (not (vlax-curve-isClosed Ename))
        )
        (cd:ENT_SetDXF Ename 70 (1+ (cdr (assoc 70 d))))
      )
      (/= (length d) l)
    )
  )
)

Jako uzupełnienie, poniżej funkcja LISP-owa, o nazwie acet-lwpline-remove-duplicate-pnts, z pakietu ExpressTools. Usuwa ona z polilinii pokrywające się punkty. Co ciekawe, nie radzi sobie w sytuacji gdy pierwszy i ostatni punkt polilinii, są takie same.

; =============================================================== ;
; acet-lwpline-remove-duplicate-pnts (ExpressTools: pljoinsup.lsp)
; Takes an entity list of lwpolylines and modifies the object
; removing neighboring duplicate points. If no duplicated points
; are found then the object will not be passed to (entmod ).
; Returns the new elist when done.
; =============================================================== ;
(defun acet-lwpline-remove-duplicate-pnts (e1 / a n lst e2)
  (setq n 0)
  (repeat (length e1)
    (setq a (nth n e1)) ;setq
    (cond
      ( (not (equal 10 (car a)))(setq e2 (cons a e2))) ;cond #1
      ( (not (equal (car lst) a))
        (setq lst (cons a lst) e2 (cons a e2)) ;setq
      ) ;cond #2
    ) ;cond close
    (setq n (+ n 1)) ;setq
  ) ;repeat
  (setq e2 (reverse e2))
    (if
      (and e2 (not (equal e1 e2)) lst) ;and
      (progn
        (if (equal 1 (length lst))
          (progn
            (entdel (cdr (assoc -1 e1)))
            (setq e2 nil)
          ) ;progn then single vertex polyline so delete it.
          (progn
            (setq e2 (subst (cons 90 (length lst)) (assoc 90 e2) e2)
          ) ;setq
          (entmod e2)
        ) ;progn else
      ) ;if
    ) ;progn then
  ) ;if
  e2
)