lukaasz Posted November 14, 2016 Report Share Posted November 14, 2016 (edited) Witam, Czy jest ktoś w stanie pomóc przy dokończeniu programu, który wypisuje nazwy elementów rysunkowych (linii, polilinii, okręgów) pod podaną warstwą? Na tą chwilę mam tak, że po podaniu nazwy warstwy wypisuje mi: 1 LWPOLYLINE 2 LWPOLYLINE 3 CIRCLE 4 INSERT itd. Potrzebuję, aby za "INSERT" wypisać jeszcze nazwę bloku, a dla pozostałych obiektów współrzędne punktów, np. dla polilinii współrzędne pkt początkowego i końcowego, dla okręgu współrzędne środka itp. Dodam, że jestem całkowicie początkujący. Oto co mam do tej pory: (defun C:raport () (setq nazwa_warstwy (getstring "Podaj nazwe warstwy: ")) (setq zb1 (ssget "X" (list (cons 8 nazwa_warstwy)))) (if(= zb1 nil) (progn (princ "\nZbior wyboru nie zawiera elementow.\n") ) ) (if (> (sslength zb1) 0) (progn (textscr) (princ "\n") (princ "Liczba elementow w zbiorze wyboru: ") (princ (sslength zb1)) (princ "\n") (setq nazwa (sslength zb1) i 0) (repeat nazwa (progn (setq wsk (ssname zb1 i) lista_dxf (entget wsk)) (setq num (cdr(car lista_dxf))) (setq w2 (cdr (assoc 0 (entget num)))) (setq wl (cons w2 wl)) (setq i (1+ i)) ) ) (setq i 0) (repeat nazwa (progn (princ i) (princ (nth i wl)) (princ "\n") (setq i (1+ i)) ) ) (graphscr) ) ) (princ) ) Edited November 14, 2016 by lukaasz Link to comment Share on other sites More sharing options...
kruszynski Posted November 15, 2016 Report Share Posted November 15, 2016 Ogólnie dobrze, ale trochę chaos zaczyna się wkradać. (setq nazwa (sslength zb1) i 0) Może przemawia przeze mnie obsesja ale bardzo ważne jest nadawanie zmiennym odpowiednich nazw . Nazwy mają być znaczące a nie mylące. Bardzo dobrze jest to wytłumaczone w książce "Czysty kod. Podręcznik dobrego programisty" Autor: Robert C. Martin . Cały niewielki rozdział jest temu poświęcony. sslength zwraca ilość i nazywanie tego "nazwa" to zły pomysł warto też stosować zmienne lokalne. np (defun C:raport ( / nazwa_warstwy zb1 nazwa i ) W wielu miejscach w programie może pojawić się zmienna "i", jeśli mamy funkcję wewnątrz funkcji, w obu wykorzystujemy i jako licznik pętli to funkcja wewnętrzna nadpisze stan zmiennej z funkcji zewnętrznej i takiego błędu można szukać godzinami. (setq wsk (ssname zb1 i) lista_dxf (entget wsk)) Moim zdaniem bardziej czytelne byłoby (setq lista_dxf (entget (ssname zb1 i))) (princ "\n") (princ "Liczba elementow w zbiorze wyboru: ") (princ (sslength zb1)) (princ "\n") można uprościć do: (princ (strcat "\nLiczba elementow w zbiorze wyboru: " (itoa (sslength zb1) ) "\n" ) Teraz najważniejsze : (setq lista_dxf (entget (ssname zb1 i))) tutaj mamy zapisany cały element. (setq EntName (cdr (assoc 0 lista_dxf ) ) ) daje nam nazwę elementu np INSERT Trzeba wykorzystać cond i rozdzielić działanie programu na odpowiednie dla każdego typu obiektów. (cond ((= EntName "INSERT") (progn (print "blok") (print (cdr (assoc 2 lista_dxf ) ) ) ; nazwa bloku )) ((or(= EntName "LIGHTWEIGHTPOLYLINE")(= EntName "POLYLINE")) (progn (print "Polilinia ") )) ((= EntName "CIRCLE")(progn (print "okrąg") ) ) ((= EntName "ARC") (progn (print "łuk") )) ((= EntName "LINE") (progn (print "linia") )) (t (print "Wybrałeś coś innego") ) ) odczytanie poszczególnych parametrów typu punkty początku, końca, środek itp to tylko kwestia odczytania odpowiedniej pozycji z list_dxf. (punkty to najczęściej kod: 10) pełną listę kodów można bez problemu znaleźć w Internecie. Można też zamienić element jako ENAME na VLA-OBJECT (setq element (vlax-ename->vla-object (ssname zb1 i) )) Wtedy to już pełna kultura obiektowości. Nazwę bloku możemy pobrać tak: (vlax-get-property element 'Name ) środek okręgu: (vlax-get-property element 'Center ) albo nawet tak: (vla-get-Center element ) tylko trzeba pamiętać, że punkty są typu variant, czyli trzeba je zamienić na czytelną postać zanim się je wyświetli: (vlax-safearray->list (vlax-variant-value (vlax-get-property element 'Center ) ) ) Powodzenia. W razie dalszych trudności proszę pisać dmatusz3 1 Link to comment Share on other sites More sharing options...
kojacek Posted November 15, 2016 Report Share Posted November 15, 2016 13 minut temu, kruszynski napisał: tutaj mamy zapisany cały element. (setq EntName (cdr (assoc 0 lista_dxf ) ) ) daje nam nazwę elementu np INSERT Trzeba wykorzystać cond i rozdzielić działanie programu na odpowiednie dla każdego typu obiektów. (cond ((= EntName "INSERT") (progn (print "blok") (print (cdr (assoc 2 lista_dxf ) ) ) ; nazwa bloku )) ((or(= EntName "LIGHTWEIGHTPOLYLINE")(= EntName "POLYLINE")) (progn (print "polilinia ") )) ((= EntName "CIRCLE")(progn (print "okrąg") ) ) ((= EntName "ARC") (progn (print "łuk") )) ((= EntName "LINE") (progn (print "linia") )) (t (print "Wybrałeś coś innego") ) ) Szczerze przyznam że po raz pierwszy spotykam się z nazwą w DXF (ename = "LIGHTWEIGHTPOLYLINE"). Link to comment Share on other sites More sharing options...
kruszynski Posted November 15, 2016 Report Share Posted November 15, 2016 Ja też się dziwiłem kiedy pierwszy raz się z tym spotkałem ;) Link to comment Share on other sites More sharing options...
kojacek Posted November 15, 2016 Report Share Posted November 15, 2016 Teraz, kruszynski napisał: Ja też się dziwiłem kiedy pierwszy raz się z tym spotkałem ;) To jakaś zmiana w oficjalnej specyfikacji DXF? Proszę o źródło. Link to comment Share on other sites More sharing options...
kruszynski Posted November 15, 2016 Report Share Posted November 15, 2016 nie pamiętam źródła. Link to comment Share on other sites More sharing options...
kojacek Posted November 15, 2016 Report Share Posted November 15, 2016 5 minut temu, kruszynski napisał: nie pamiętam źródła. No to może jakiś plik DXF z takim obiektem, albo DWG, żeby można entget-em pobrać "LIGHTWEIGHTPOLYLINE"... albo może jakiś lispowy kod typu entmake z "LIGHTWEIGHTPOLYLINE"? Da się? Link to comment Share on other sites More sharing options...
lukaasz Posted November 15, 2016 Author Report Share Posted November 15, 2016 (edited) 9 godzin temu, kruszynski napisał: Ogólnie dobrze, ale trochę chaos zaczyna się wkradać. (setq nazwa (sslength zb1) i 0) Może przemawia przeze mnie obsesja ale bardzo ważne jest nadawanie zmiennym odpowiednich nazw . Nazwy mają być znaczące a nie mylące. Bardzo dobrze jest to wytłumaczone w książce "Czysty kod. Podręcznik dobrego programisty" Autor: Robert C. Martin . Cały niewielki rozdział jest temu poświęcony. sslength zwraca ilość i nazywanie tego "nazwa" to zły pomysł warto też stosować zmienne lokalne. np (defun C:raport ( / nazwa_warstwy zb1 nazwa i ) W wielu miejscach w programie może pojawić się zmienna "i", jeśli mamy funkcję wewnątrz funkcji, w obu wykorzystujemy i jako licznik pętli to funkcja wewnętrzna nadpisze stan zmiennej z funkcji zewnętrznej i takiego błędu można szukać godzinami. (setq wsk (ssname zb1 i) lista_dxf (entget wsk)) Moim zdaniem bardziej czytelne byłoby (setq lista_dxf (entget (ssname zb1 i))) (princ "\n") (princ "Liczba elementow w zbiorze wyboru: ") (princ (sslength zb1)) (princ "\n") można uprościć do: (princ (strcat "\nLiczba elementow w zbiorze wyboru: " (itoa (sslength zb1) ) "\n" ) Teraz najważniejsze : (setq lista_dxf (entget (ssname zb1 i))) tutaj mamy zapisany cały element. (setq EntName (cdr (assoc 0 lista_dxf ) ) ) daje nam nazwę elementu np INSERT Trzeba wykorzystać cond i rozdzielić działanie programu na odpowiednie dla każdego typu obiektów. (cond ((= EntName "INSERT") (progn (print "blok") (print (cdr (assoc 2 lista_dxf ) ) ) ; nazwa bloku )) ((or(= EntName "LIGHTWEIGHTPOLYLINE")(= EntName "POLYLINE")) (progn (print "polilinia ") )) ((= EntName "CIRCLE")(progn (print "okrąg") ) ) ((= EntName "ARC") (progn (print "łuk") )) ((= EntName "LINE") (progn (print "linia") )) (t (print "Wybrałeś coś innego") ) ) odczytanie poszczególnych parametrów typu punkty początku, końca, środek itp to tylko kwestia odczytania odpowiedniej pozycji z list_dxf. (punkty to najczęściej kod: 10) pełną listę kodów można bez problemu znaleźć w Internecie. Można też zamienić element jako ENAME na VLA-OBJECT (setq element (vlax-ename->vla-object (ssname zb1 i) )) Wtedy to już pełna kultura obiektowości. Nazwę bloku możemy pobrać tak: (vlax-get-property element 'Name ) środek okręgu: (vlax-get-property element 'Center ) albo nawet tak: (vla-get-Center element ) tylko trzeba pamiętać, że punkty są typu variant, czyli trzeba je zamienić na czytelną postać zanim się je wyświetli: (vlax-safearray->list (vlax-variant-value (vlax-get-property element 'Center ) ) ) Powodzenia. W razie dalszych trudności proszę pisać Super, bardzo dziękuję za wskazówki. Problem ma tylko taki, że coś mi wyświetla cały czas tą samą nazwę bloku przy każdym INSERT, a nie wiem za bardzo czemu. (defun C:raport () ;tworzy raport obiektow znajdujacych sie na danej warstwie (setq dlugosc_warstwy (getstring "Podaj nazwe warstwy: ")) (setq zb1 (ssget "X" (list (cons 8 dlugosc_warstwy)))) (if(= zb1 nil) (progn (princ "\nZbior wyboru nie zawiera elementow.\n") ) ) (if (> (sslength zb1) 0) (progn (textscr) (princ "\n") (princ "Liczba elementow w zbiorze wyboru: ") (princ (sslength zb1)) (princ "\n") (setq dlugosc (sslength zb1) i 0) (repeat dlugosc (progn (setq lista_dxf (entget (ssname zb1 i))) (setq EntName (cdr (assoc 0 lista_dxf ))) (setq num (cdr(car lista_dxf))) (setq wpocz2 (cdr (assoc 0 (entget num)))) (setq wpoczl (cons wpocz2 wpoczl)) (setq i (1+ i)) ) ) (setq i 0) (repeat dlugosc (cond ((= EntName "INSERT") (progn (princ i) (princ (nth i wpoczl)) (princ (cdr (assoc 2 lista_dxf ) ) ) ; nazwa bloku (princ "\n") )) ((or(= EntName "LIGHTWEIGHTPOLYLINE")(= EntName "POLYLINE")) (progn (princ "Polilinia ") )) ((= EntName "CIRCLE")(progn (princ "okrąg") ) ) ((= EntName "ARC") (progn (princ "łuk") )) ((= EntName "LINE") (progn (princ "linia") )) (t (princ "Wybrales cos innego") ) ) (setq i (1+ i)) ) (graphscr) ) ) (princ) ) Edited November 15, 2016 by lukaasz Link to comment Share on other sites More sharing options...
kruszynski Posted November 16, 2016 Report Share Posted November 16, 2016 może to dlatego, że są dwie pętle (repeat ) W pierwszej przypisywana jest kolejno wartość do zmiennej lista_dxf. Druga pętla przechodzi tyle samo razy przez zmienną, której wartość nie jest nigdzie aktualizowana. Link to comment Share on other sites More sharing options...
kojacek Posted November 16, 2016 Report Share Posted November 16, 2016 32 minuty temu, kruszynski napisał: może to dlatego, że są dwie pętle (repeat ) W pierwszej przypisywana jest kolejno wartość do zmiennej lista_dxf. Druga pętla przechodzi tyle samo razy przez zmienną, której wartość nie jest nigdzie aktualizowana. Problemem są zmienne lokalne, a właściwie ich brak. Zresztą w kodzie problemów jest więcej. A co tam z LIGHTWEIGHTPOLYLINE? Doczekam się wiarygodnego przykładu? Link to comment Share on other sites More sharing options...
dmatusz3 Posted November 29, 2016 Report Share Posted November 29, 2016 Myślę, że dzięki podpowiedziom udało się uzyskać zaliczenie. Link to comment Share on other sites More sharing options...
Recommended Posts