entmod na wielu obiektach


Rekomendowane odpowiedzi

Dzień dobry.

Próbuję wykonać pewną operację na wielu powierzchniach 3DFace. Dla przykładu pomnożyć współrzędną "Z" wierzchołków razy 10. Korzystając z kilku podpowiedzi:
https://www.zwcad.pl/help/lisp-help/246-subst.html
http://forums.augi.com/showthread.php?120834-How-to-know-name-of-Entity-by-ssget
Stworzyłem coś takiego:

(defun c:zz ()
(if (setq ssSelections (ssget (list (cons 0 "3DFACE"))))
 (repeat (setq intCount (sslength ssSelections))
  (setq intCount     (1- intCount)
        entSelection (ssname ssSelections intCount)
        lstEntity    (entget entSelection)
  )
   		;współrzędne wierzchołka 1
		(setq wierzcholek1 (assoc 10 lstEntity))
			(setq x1 (nth 1 wierzcholek1))
			(setq y1 (nth 2 wierzcholek1))
			(setq z1 (nth 3 wierzcholek1))
		;współrzędne wierzchołka 2
			(setq wierzcholek2 (assoc 11 lstEntity))
			(setq x2 (nth 1 wierzcholek2))
			(setq y2 (nth 2 wierzcholek2))
			(setq z2 (nth 3 wierzcholek2))
		 
    ;podmiana punktu 1
(setq lstEntity (subst (cons 10 (list	x1 y1 (* z1 10)) (assoc '10 lstEntity ) lstEntity ) ))
(entmod lstEntity)
	;podmiana punktu 2
(setq lstEntity (subst (cons 11 (list	x2 y2 (* z2 10)) (assoc '11 lstEntity ) lstEntity ) ))
(entmod lstEntity)

 );koniec repeat
 );koniec if
 (print)
);Koniec

W powyższym kodzie pominąłem dwa ostatnie punkty. Chciałem pokazać tylko ideę.
Co robię źle, że to nie działa?

Pozdrawiam

Odnośnik do komentarza
Udostępnij na innych stronach

Prawie wszystko. Począwszy od:
1) braku zmiennych lokalnych (zobacz: https://kojacek.wordpress.com/2015/12/20/symbole-zmienne/). 
2) Potem pomysł z mnożeniem wartości współrzędnej z. Operacje dodawania/odejmowania wydają się być chyba bardziej naturalne (sprawdź mnożenie 1 i 0 przez dowolną wartość). Na marginesie: zmiana składowej Z wszystkich punktów obiektu, o tę samą wartość, to w rzeczywistości przesunięcie go w przestrzeni - to można też robić prościej (command MOVE, lub vla-Move dla ActiveX)
3) Ponadto ja bym nie użył (ze względu na wydajność) repeat, tylko raczej foreach dla listy otrzymanej ze zbioru wskazań. 
4) Tak samo zmieniłbym całą listę, i tylko raz wywołał entmod
Oczywiście dwa ostatnie punkty nie są szczególnymi błędami.

Poczytaj też o: https://kojacek.wordpress.com/2015/11/04/cadpl-pack/ Jest tam parę dość użytecznych rzeczy.
 

Edytowane przez kojacek
Odnośnik do komentarza
Udostępnij na innych stronach

Oczywiście zajrzę na Pańską stronę. Każda dodatkowa wiedza jest cenna.
Do tej pory myślałem, że deklarowanie zmiennych to pomoc przy dużych kodach, a nie konieczność.
Czy to może być powodem nie działania programu? 
Program działa do linijki: podmiana punktu 1
Natomiast mnożenie zmiennej "Z" to tylko przykład.

Pozdrawiam  

Odnośnik do komentarza
Udostępnij na innych stronach

Zobacz to:

(setq NowyZ 152)

(defun C:ZZ (/ ss :chFaceZ)
  (defun :chFaceZ (En Val / l d n p)
    (setq l '(10 11 12 13)
          d (entget En)
          n (vl-remove-if '(lambda (%)(member (car %) l)) d)
          p (vl-remove-if-not '(lambda (%)(member (car %) l)) d)
          p (mapcar '(lambda (%)
                       (list (car %)(cadr %)(caddr %)(+ Val (cadddr %)))) p)
    )
    (entmod (append n p))
  )
  (if
    (setq ss (ssget '((0 . "3DFACE"))))
    (foreach % (cd:SSX_Convert ss 0)
      (:chFaceZ % NowyZ)
    )
  )
  (princ)
)

Dodaje wartość zmiennej globalnej NowyZ do składowej z każdego wierzchołka wybranych 3DFace. Wykorzystuje cd:SSX_Convert  ze wspomnianego CADPL-Pack'a

Odnośnik do komentarza
Udostępnij na innych stronach

Mój poziom wiedzy o lispie jest o kilka poziomów za niski, żeby w 100% zrozumieć powyższy kod... a może strach ma wielkie oczy.
Żeby ruszyć dalej z nauką muszę wiedzieć gdzie robię błędy na obecnym etapie.

Tak czy siak dziękuję za pomoc

PS docelowy kod ma zmieniać wsp wierzchołków z takich:
W1:  x1=5.12345678  y1=3.23456789 z1=7.42345678
na takie:
W1:  x1=5.12000000  y1=3.23000000  z1=7.42000000
Czyli niewielkie przesunięcie. 
Uważałem, że nie ma potrzeby pisać całego kodu, dlatego posłużyłem się przykładem (* z 10)

Odnośnik do komentarza
Udostępnij na innych stronach

Problemem w kodzie z pierwszego przykładu jest:
LISP czyli  Lost In Stupid Parentheses :wink:Po uruchomieniu kodu w pasku poleceń pojawia się :

Error: too many arguments

czyli któraś funkcja została wywołana ze zbyt dużą ilością argumentów. Pozostaje nam znaleźć która.
Tak na pierwszy rzut oka wyglądało OK, więc spróbowałem wykonać kod "po linijce"
Okazało się, że komunikat wyświetla linijka

(setq lstEntity (subst (cons 10 (list x1 y1 (* z1 10))  (assoc '10 lstEntity ) lstEntity ) ))

Notepad++ ma kolorowanie składni i podświetlanie nawiasów. Więc łatwo widać, że to cons, ma nawias zbyt daleko.

Notepad++.png

Czyli cały poprawiony kod:

(defun c:zz ()
(if (setq ssSelections (ssget (list (cons 0 "3DFace"))))
 (repeat (setq intCount (sslength ssSelections))
  (setq intCount (1- intCount)
        entSelection (ssname ssSelections intCount)
        lstEntity (entget entSelection)
  )
           ;współrzędne wierzchołka 1
        (setq wierzcholek1 (assoc 10 lstEntity))
            (setq x1 (nth 1 wierzcholek1))
            (setq y1 (nth 2 wierzcholek1))
            (setq z1 (nth 3 wierzcholek1))
        ;współrzędne wierzchołka 2
            (setq wierzcholek2 (assoc 11 lstEntity))
            (setq x2 (nth 1 wierzcholek2))
            (setq y2 (nth 2 wierzcholek2))
            (setq z2 (nth 3 wierzcholek2))
         
    ;podmiana punktu 1
(setq lstEntity (subst (cons 10 (list x1 y1 (* z1 10) ))  (assoc '10 lstEntity ) lstEntity ) )
(entmod lstEntity)
    ;podmiana punktu 2
(setq lstEntity (subst (cons 11 (list x2 y2 (* z2 10) ) ) (assoc '11 lstEntity ) lstEntity ) )
(entmod lstEntity)

 );koniec repeat
 );koniec if
 (print)
);Koniec

 

Odnośnik do komentarza
Udostępnij na innych stronach

Lost In Stupid Parentheses  - to moje nowe motto;)

Nie mogę uwierzyć,że to o to chodziło.
Co do powyższego kodu jest jeszcze jeden bug. Zmienia tylko jeden wierzchołek. Prawdopodobnie dlatego, że przy drugim punkcie odwołuję się do lstEntity (przed zmianą 1 punktu).
Rozwiązałem to tak:

(defun ChangeVx ( NrVx / )

 (repeat (setq intCount (sslength ssSelections))
  (setq intCount     (1- intCount)
        entSelection (ssname ssSelections intCount)
        lstEntity    (entget entSelection)
   )
  		;Vertex 
		(setq wierzcholek (assoc NrVx lstEntity))
			(setq x1 (nth 1 wierzcholek))
			(setq y1 (nth 2 wierzcholek))
			(setq z1 (nth 3 wierzcholek))
 
    ;podmiana punktu 
(setq nowaDef (subst (cons NrVx (list		(atof (rtos x1 2 2))
										(atof (rtos y1 2 2))
										(atof (rtos z1 2 2))
															)) (assoc 'NrVx lstEntity ) lstEntity ))
(setq nowaDef (append lstEntity (list (cons NrVx (list 	(atof (rtos x1 2 2))
														(atof (rtos y1 2 2))
														(atof (rtos z1 2 2)))) ) ) )

(entmod nowaDef)
 
 );koniec repeat
 (print)
);

(defun c:zz ()
(setq ssSelections (ssget (list (cons 0 "3DFACE"))))
(setq NrVx 10)
(repeat 4
	(ChangeVx NrVx )
	(setq NrVx (1+ NrVx))
);end repeat
);KONIEC

A zamiast:
(atof (rtos x 2 2))
można tak:
(/ (fix (* x 100.)) 100.0)

Dziękuję za wszystkie podpowiedzi

Odnośnik do komentarza
Udostępnij na innych stronach

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Gość
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Usuń formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

Ładowanie