lukaasz Opublikowano 14 Listopada 2016 Zgłoś Opublikowano 14 Listopada 2016 (edytowane) 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) ) Edytowane 14 Listopada 2016 przez lukaasz
kruszynski Opublikowano 15 Listopada 2016 Zgłoś Opublikowano 15 Listopada 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
kojacek Opublikowano 15 Listopada 2016 Zgłoś Opublikowano 15 Listopada 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").
kruszynski Opublikowano 15 Listopada 2016 Zgłoś Opublikowano 15 Listopada 2016 Ja też się dziwiłem kiedy pierwszy raz się z tym spotkałem ;)
kojacek Opublikowano 15 Listopada 2016 Zgłoś Opublikowano 15 Listopada 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.
kojacek Opublikowano 15 Listopada 2016 Zgłoś Opublikowano 15 Listopada 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ę?
lukaasz Opublikowano 15 Listopada 2016 Autor Zgłoś Opublikowano 15 Listopada 2016 (edytowane) 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) ) Edytowane 15 Listopada 2016 przez lukaasz
kruszynski Opublikowano 16 Listopada 2016 Zgłoś Opublikowano 16 Listopada 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.
kojacek Opublikowano 16 Listopada 2016 Zgłoś Opublikowano 16 Listopada 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?
dmatusz3 Opublikowano 29 Listopada 2016 Zgłoś Opublikowano 29 Listopada 2016 Myślę, że dzięki podpowiedziom udało się uzyskać zaliczenie.
Rekomendowane odpowiedzi