[Lisp] Nazwa bloku i współrzędne punktów [rozwiązany]


Recommended Posts

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 by lukaasz
Link to comment
Share on other sites

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ć

 

Link to comment
Share on other sites

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

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 by lukaasz
Link to comment
Share on other sites

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

  • 2 weeks later...
  • dmatusz3 changed the title to [Lisp] Nazwa bloku i współrzędne punktów [rozwiązany]
  • dmatusz3 locked this topic
Guest
This topic is now closed to further replies.