kojacek

Użytkownik forum
  • Postów

    252
  • Dołączył

  • Ostatnia wizyta

  • Wygrane w rankingu

    35

Treść opublikowana przez kojacek

  1. A propos tych profili. Tak sobie myślę że jeśli jedziemy z bloków, to można się umówić że definicja takiego bloku może składać się zawsze i tylko z jednego obiektu będącym: 1) Zamkniętą LWPOLYLINE (tak jak tutaj jakieś tam IP które testowaliśmy) 2) Obiektu typu REGION - i tutaj możemy sobie pozwolić na bardziej wydumane kształty (np. rura, czy profil z otworami). Warunek - musi to być jeden obiekt I wtedy, można dopracować program tak, aby można było wybrać tylko taki rodzaj bloku (jeden obiekt jak powyżej) - reszta byłaby odrzucana.
  2. Przepraszam, jeśli można... Czy nie za szybko zamykamy? Powinno się to jeszcze poprawić: 1. Obsługa błędów. Wywalenie command. 2. Wybieranie bloków, skalowanie ewentualnie. 3. Sprawdzenie bloku (jeden profil) 4. Wprowadzenie innych zakończeń (trzy typy - jak tu Martin pokazywał) 5. (Opcjonalnie) te zabawy ze zmianą punktów (9 wstawień)
  3. Nie no, to dramat jakiś z tym zwcad... a pack teraz załadowany jest?
  4. Poprawiony kod (zamiast CD:SYS_UNDOSTART powinno być CD:SYS_UNDOBEGIN) Cały kod: ; =========================================================================================== ; (defun C:EXTRINS (/ InsName StartP EndP PathEnt InsObj Cmd) (if (setq StartP (getpoint "\nPierwszy punkt linii definiującej ścieżkę: ")) (if (setq EndP (getpoint StartP "\nKoniec ścieżki: ")) (if (and (setq InsName (getstring "\nPodaj nazwe bloku: ")) (member (strcase InsName) (mapcar 'strcase (cd:SYS_CollList "BLOCK" (+ 1 2 4 8))) ) ) (progn (cd:SYS_UndoBegin) (setq Cmd (getvar "CMDECHO")) (setq InsObj (cd:BLK_InsertBlock StartP InsName '(1 1 1) 0 T)) (SetInsertZOrient (NewVect StartP EndP) (setq InsObj (vlax-vla-object->ename InsObj) ) ) (setq PathEnt (cd:ENT_MakeLine (getvar "CTAB") StartP EndP T)) (vla-explode (vlax-ename->vla-object InsObj)) (entdel InsObj) (setvar "CMDECHO" 0) (command "_.EXTRUDE" (entlast) "" "_path" PathEnt) (setvar "CMDECHO" 1) (entdel PathEnt) (cd:SYS_UndoEnd) ) ) ) ) (princ) ) ; =========================================================================================== ; (defun NewVect (p1 p2 / dt sq sm um uv) (setq dt (mapcar '- p2 p1) sq (mapcar '* dt dt) sm (apply '+ sq) um (sqrt sm) uv (mapcar '/ dt (list um um um)) ) ) ; =========================================================================================== ; (defun SetInsertZOrient (ExtrVec Ename / e b) (setq e (entget Ename) b (trans (cdr (assoc 10 e)) Ename ExtrVec) e (subst (cons 10 b)(assoc 10 e) e) e (subst (cons 50 0.0)(assoc 50 e) e) e (subst (cons 210 ExtrVec)(assoc 210 e) e) ) (entmod e) ) ; =========================================================================================== ; (princ)
  5. Działa z blokiem teraz czy nie? A jeśli działa to jest źle czy dobrze?
  6. Spokojnie, póki co oczekuję informacji czy to co podałem działa, i czy działa w sposób, ogólnie oczekiwany. Nie da się zrobić wszystkiego na raz, zwłaszcza że zmienia się co chwilę zdanie (raz blok fajny, innym razem niefajny).
  7. Zrobiłem to na podstawie Twojego pliku DWG który tu opublikowałeś na początku. Tam jest jest blok IPE500, testowałem LISP-a na tym właśnie przykładzie. Blok jest o tyle dobry bo można go "porządnie" zdefiniować (właśnie zamknięcie polilinii), jak też określić dla całości orientację (gdzie "dół / góra) itp.
  8. Na sam początek. Od razu pewne uwagi: 1) Polecenie EXTRINS wyciąga profil (jedna polilinia w definicji bloku), po ścieżce będącej linią utworzoną przez wskazanie dwóch punktów. 2) To na razie robocza "brudna" wersja do testowania - bez obsługi błędów i z commandem (docelowo bez niego bym wolał) 3) Podczas pracy układ współrzędnych powinien być globalnym (nie ma potrzeby niczego zmieniać) 4) Na razie blok profilu trzeba podać ręcznie przez nazwę. W przyszłości można zastosować listę w oknie i (lub) przez wskazanie bloku. 4) Profil jest ustawiany "prostopadle" do linii wyciągnięcia. To podstawowa cecha. W przyszłości można będzie ustawić go "pod kątem" (generalnie na płaszczyźnie GUW raczej.) 5) Testujcie. Nie wiem czy to będzie chodzić na wszystkich waszych ZwCAD-ach, ale zobaczymy. 6) Ostatnia uwaga, trzeba załadować CADPL-Pack'a 7) Kod: ; =========================================================================================== ; (defun C:EXTRINS (/ InsName StartP EndP PathEnt InsObj Cmd) (if (setq StartP (getpoint "\nPierwszy punkt linii definiującej ścieżkę: ")) (if (setq EndP (getpoint StartP "\nKoniec ścieżki: ")) (if (and (setq InsName (getstring "\nPodaj nazwe bloku: ")) (member (strcase InsName) (mapcar 'strcase (cd:SYS_CollList "BLOCK" (+ 1 2 4 8))) ) ) (progn (cd:SYS_UndoStart) (setq Cmd (getvar "CMDECHO")) (setq InsObj (cd:BLK_InsertBlock StartP InsName '(1 1 1) 0 T)) (SetInsertZOrient (NewVect StartP EndP) (setq InsObj (vlax-vla-object->ename InsObj) ) ) (setq PathEnt (cd:ENT_MakeLine (getvar "CTAB") StartP EndP T)) (vla-explode (vlax-ename->vla-object InsObj)) (entdel InsObj) (setvar "CMDECHO" 0) (command "_.EXTRUDE" (entlast) "" "_path" PathEnt) (setvar "CMDECHO" 1) (entdel PathEnt) (cd:SYS_UndoEnd) ) ) ) ) (princ) ) ; =========================================================================================== ; (defun NewVect (p1 p2 / dt sq sm um uv) (setq dt (mapcar '- p2 p1) sq (mapcar '* dt dt) sm (apply '+ sq) um (sqrt sm) uv (mapcar '/ dt (list um um um)) ) ) ; =========================================================================================== ; (defun SetInsertZOrient (ExtrVec Ename / e b) (setq e (entget Ename) b (trans (cdr (assoc 10 e)) Ename ExtrVec) e (subst (cons 10 b)(assoc 10 e) e) e (subst (cons 50 0.0)(assoc 50 e) e) e (subst (cons 210 ExtrVec)(assoc 210 e) e) ) (entmod e) ) ; =========================================================================================== ; (princ)
  9. Funkcja z przedrostkiem C: to specjalna definicja funkcji lispowej - najoględniej mówiąc tworzy polecenie AutoCAD-a, zdefiniowane w LISP-ie. Wywołanie jej działa jak polecenie, można je wywołać z linii poleceń. Taka funkcja nie może mieć argumentów. Natomiast "zwykłe" funkcje można wywołać w linii poleceń, ale trzeba je wywoływać w pełnej składni wymaganej przez interpreter LISP-a, czyli w nawiasach i z argumentami (jeśli funkcja je posiada). I tak, namaluj coś i w linii poleceń napisz: (entlast) funkcja zwróci ename ostatniego obiektu. Teraz wywołaj funkcję z argumentem np. : (entget (entlast)) dostaniesz listę DXF danych tego obiektu. Tak samo wywołujesz funkcję SelRect: (SelRect) Drugi problem. Kierunek polilinii. Potrzebujesz funkcji napisanej przez gile'a. Wygląda tak: ;; Clockwise-p - Gilles Chanteau (gile) ;; Returns T if p1,p2,p3 are clockwise oriented (defun gc:clockwise-p (p1 p2 p3) (< (sin (- (angle p1 p3) (angle p1 p2))) -1e-14) ) Zwraca T jeśli 3 punkty podane jako argumenty funkcji tworzą kąt zorientowany zgodnie z ruchem wskazówek zegara, lub nil w przeciwnym wypadku. Potem można już zdefiniować polecenie sprawdzające polilinię. Musi ona mieć co najmniej dwa wierzchołki. Funkcja może wyglądać tak: (defun C:TESTCLP (/ e d p) (if (and (setq e (entsel "\nWybierz polilinie: ")) (= (cdr (assoc 0 (setq d (entget (car e))))) "LWPOLYLINE") ) (if (> (length (setq p (cd:DXF_massoc 10 d))) 2) (gc:clockwise-p (car p)(cadr p)(caddr p)) ) ) )
  10. Tymczasem wróćmy (bośmy nieco "zboczyli"... ;) ) do wyboru polilinii. Krótko jeszcze o "zadaniu domowym". Spójrzmy na obrazek porównujący prostokąt z "kokardką": Pożądany przez nas czworokąt będący prostokątem można sprawdzić też w ten sposób: Weźmy dwa sąsiednie boki (np. 1-2 i 2-3). Wybierzmy najdłuższy z nich (tu będzie to 1-2). I teraz sprawdzamy: w prostokącie ten najdłuższy z boków musi być krótszy od długości przekątnej (np. 1-4), dodatkowo oczywiście to (przekątne) jednocześnie muszą być sobie równe. I to chyba w zupełności wystarczy? Kod "zadania domowego": (defun SelRect (/ e d rect-p) (defun rect-p (p / d) (if ; jezeli (not (zerop (distance (car p)(cadddr p)))) ; 1 i 4 pkt sie nie pokrywaja (and ; sprawdz (equal ; czy jest rowna (setq d (distance (car p)(caddr p))) ; dlugosc 1 przekatnej (distance (cadr p)(cadddr p)) ; i 2 przekatnej? 0.001 ) (< ; i najwiekszy (max ; bok z 1 i 2 (distance (car p)(cadr p)) ; jest (distance (cadr p)(caddr p)) ; mniejszy ) d ; od przekatnej ) ) ; T (spelnia warunki) ) ; nil (nie spelnia) ) (if (and (setq e (entsel "\nWskaż prostokąt: ")) ; jest wybor (= (cdr (assoc 0 (setq d (entget (car e))))) "LWPOLYLINE") ; to LWPoly (= 1 (logand 1 (cdr (assoc 70 d)))) ; jest zamknieta (zerop (apply '+ (mapcar 'abs (cd:DXF_massoc 42 d)))) ; nie ma seg. lukowych (= (cdr (assoc 90 d)) 4) ; ma 4 wierzcholki (rect-p (cd:DXF_massoc 10 d)) ; jest prostokatem ) (princ "\nOk") (princ "\nŹle. ") ) ) wzbogacony o komentarze, które pozwolą łatwiej prześledzić działanie.
  11. Chyba się nie rozumiemy do końca. W mojej opinii budowanie funkcji (a bibliotecznych szczególnie) ma na celu (między innymi) skracanie kodu. Przykłady które zaprezentowałeś idą w przeciwnym kierunku. "Moje" ośmiolinijkowe <and> (z jedną tylko funkcją lokalną) zastępujesz sześcioma funkcjami (już nie liczę ilości linii). Na koniec twierdzisz że jest to bardziej czytelne. Pozornie tak (są nazwy), w istocie śledzenie kodu jest jednak dużo trudniejsze. Zobacz. Przykładowa funkcja biblioteczna (stosunkowo krótka) może nas informować jednocześnie czy polilinia jest zamknięta, czy jest PLINEGEN i czy zawiera szegmenty łukowe: (defun GetPolyProp (Ent / d) (setq d (entget Ent)) (+ (cdr (assoc 70 d)) (if (zerop (apply '+ (mapcar 'abs (cd:DXF_massoc 42 d)))) 0 256) ) ) Wywołanie: (GetPolyProp (car (entsel))) Stosuję jedną funkcję (tylko jedno wywołanie), i mam jednocześnie trzy informacje. Takie podejście (skracanie kodu) uważam za lepsze jeśli chodzi o czytelność. Oczywiście, abyśmy się zrozumieli - w żadnym wypadku nie deprecjonuję innych rozwiązań.
  12. Zaraz strzelanie. Są co najmniej dwie drogi obejścia nieszczęśliwego ESC. Dlaczego o jednej i (tylko jednej) właśnie już teraz ma się dowiedzieć Iskra i każdy inny? Oczywiście może, ale (w mojej opinii) ważniejszym jest skoncentrowanie się na szerszym spojrzeniu na zagadnienie poprawnego wyboru obiektu. Określeniu warunków, i ich sprawdzeniu itp. Obsługa błędów, ogólnie rzecz biorąc jest zwykle "wisienką na torcie". Nadal nie jestem przekonany czy HasArcSegment jest czytelniejsze niźli (zerop (apply '+ (mapcar 'abs (cd:DXF_massoc 42 EntityList)))) biorąc pod uwagę, że mogę dodać komentarz właśnie: ; Ma sgementy łukowe? a działanie i tak (w obu przypadkach) trzeba prześledzić w ten sam sposób. Oczywiście to moje subiektywne zdanie.
  13. Pozwolę sobie wyrazić swoją opinię, w sprawie trzech powyższych punktów. Ad 1. Zgoda, ale chyba za wcześnie na to wszystko. Do tej pory odnosiłem wrażenie że wątek mając nieco charakter edukacyjny, powoli rośnie zwiększając poziom zaawansowania. Zwłaszcza że kolega Iskra (zakładając wątek) sam nadmienił że się dopiero uczy. Napisał kawałek dość dobrego kodu (w ogólności co do zasady), nie wystrzegł się paru błędów, ale nie zniechęcajmy go jednak na samym początku. Na vl-catch-all-apply przyjdzie jeszcze czas. Na razie bez radykalnego zawsze i absolutnie. Póki co proste rzeczy, pytania i odpowiedzi. Chce wiedzieć, pyta, ma potencjał, na wszystko przyjdzie czas. Popatrz (że znów wrócę do CAD-Pack'a), nie mówię że wszystko jest do d*py, weź no funkcję cd:USR_EntSelObj, daj se spokój bo ona jest git... Na marginesie, warto na nią też popatrzeć. Ad 2. Różnić się będę także co do rzekomej czytelności kodu. Wydaje mi się że przedstawiona propozycja zaciemnia a nie rozjaśnia. Ogólnie jestem zwolennikiem stosowania funkcji w funkcji (mającej charakter lokalny) w dwóch przypadkach. Po pierwsze: podfunkcja (tak ją nazwijmy umownie), wywoływana jest wielokrotnie, lub (po drugie), jest na tyle obszerna że zaciemnia właśnie kod główny. Ten drugi przypadek widać w zastosowaniu funkcji dia wewnątrz SelRect. Wszystkie inne wywołania w and, (typ obiektu, zamknięcie, bulge itp.) wydają się na tyle proste że nie widzę potrzeby definiowania ich jako osobne funkcje. Zwłaszcza jako funkcje lokalne (mające zasięg tylko wewnątrz innej jednej funkcji). Spójrzmy, przykład pierwszy z brzegu. Kod: (defun IsPolyline (Entity / ) (= (cdr (assoc 0 Entity)) "LWPOLYLINE") ) właściwie niczego nie wnosi (oprócz zwiększenia objętości), bowiem samo: (= (cdr (assoc 0 Entity)) "LWPOLYLINE") wydaje się być i tak czytelne. Ewentualnie można je opatrzyć komentarzem. Powtórzę raz jeszcze - zwłaszcza jako funkcja lokalna. Co innego gdyby to była funkcja biblioteczna (mogąca mieć wielokrotne zastosowanie w wielu miejscach). Jestem zagorzałym zwolennikiem tworzenia funkcji bibliotecznych. Jednak uważam, należy zachować tutaj pewien umiar i szukać możliwie uniwersalnego zastosowania. Bowiem (jeszcze na tym przykładzie), gdyby nawet twoja IsPolyline, była nawet funkcją biblioteczną, jej sens i tak jest mocno wątpliwy. Bowiem tym tropem trzeba by stworzyć tyle funkcji ile jest typów obiektów (Isline, IsArc, IsCircle... etc.) Nie trzeba wiele analizować że nie ma to sensu. W tym przypadku funkcja biblioteczna mogłaby być jedna i sprawdzać czy podany obiekt jest akceptowany wg jakiegoś kryterium (tutaj rodzaj obiektu). Na przykład definicja: (defun GetTypeObj (Ent TypeLst) (car (member (cdr (assoc 0 (entget Ent))) TypeLst)) ) i potem przykładowe wywołania: (GetTypeObj (car (entsel)) '("LWPOLYLINE" "LINE" "ARC")) pozwala określić ze wskazania czy to jest polilnia albo linia albo łuk czy: (GetTypeObj (car (entsel)) '("LWPOLYLINE")) zawęzić typ tylko do polilinii. Podsumowując - w mojej opinii - poprzez przerost definicji funkcji zaciemniłeś, a nie rozjaśniłeś kod. Ad 3. Powtórzę to co w Ad 1. Ogólnie zgoda, niemniej tutaj testujemy budowanie prostej funkcji ilustrując jej działanie, tak aby była zrozumiała, na tym poziomie ogólności. W tej chwili potrzebujemy informacji czy wybór jest ok czy be. Gdy to przejdziemy nastąpić może ciąg dalszy (coś się dzieje gdy jest ok, coś innego gdy jest be).
  14. No to zadanie domowe nam urosło... ;) Proponuję dodatkowo sprawdzenie (porównanie) pól polilini: Otrzymanych z pomnożenia długości 1 i drugiego boku, oraz właściwości Area obiektu. Zdaje się że każde "skrzywienie" geometrii (pomimo równych przekątnych) powinno dać różne wyniki. Zmodyfikowana SelRect wygląda tak: (defun SelRect (/ e d dia) (defun dia (l p) (if (not (zerop (distance (car p)(cadddr p)))) (and (equal (distance (car p)(caddr p)) (distance (cadr p)(cadddr p)) 0.001 ) (equal (* (distance (car p)(cadr p))(distance (cadr p)(caddr p))) (vla-get-Area (vlax-ename->vla-object l)) 0.001 ) ) ) ) (if (and (setq e (entsel "\nWskaż prostokąt: ")) (= (cdr (assoc 0 (setq d (entget (car e))))) "LWPOLYLINE") (= 1 (logand 1 (cdr (assoc 70 d)))) (zerop (apply '+ (mapcar 'abs (cd:DXF_massoc 42 d)))) (= (cdr (assoc 90 d)) 4) (dia (car e)(cd:DXF_massoc 10 d)) ) (princ "\nOk") (princ "\nŹle. ") ) )
  15. Zadanie domowe rozwiązane bardzo dobrze (choć bez funkcji), ale ok. Funkcja może wygladać tak: (defun SelRect (/ e d dia) (defun dia (p) (if (not (zerop (distance (car p)(cadddr p)))) (equal (distance (car p)(caddr p)) (distance (cadr p)(cadddr p)) 0.001 ) ) ) (if (and (setq e (entsel "\nWskaż prostokąt: ")) (= (cdr (assoc 0 (setq d (entget (car e))))) "LWPOLYLINE") (= 1 (logand 1 (cdr (assoc 70 d)))) (zerop (apply '+ (mapcar 'abs (cd:DXF_massoc 42 d)))) (= (cdr (assoc 90 d)) 4) (dia (cd:DXF_massoc 10 d)) ) (princ "\nOk") (princ "\nŹle. ") )) SelRect, ma w sobie zdefiniowaną funkcję dia, która zwraca T jeżeli z listy punktów wynika że odległości 1-3 i 2-4 (przekątne) są równe (z tolerancją .001). Trzeba zwrócić uwagę na sprawdzenie czy pierwszy i ostatni punkt się nie pokrywają - eliminuje to przypadek listy 4 współrzędnych definuijących w rzeczywistości trójkąt, a nie czworokąt. Funkcja jest argumentacyjna, i wstawiona jest jako kolejny element w and. Czyli wyszło teraz tak: - coś wybrane - to jest LWPoly - jest zamknięta - nie ma łuków - ma 4 wierzchołki - przekątne są równe... Wracając do naszej funkcji wyboru, można niektóre warunki zargumentyzować np. otwarta/zamknięta itp. W następnym odcinku możemy to spróbować. Masz rację! Trzeba dodać jeszcze jeden inny warunek. Jaki będzie najprościej?
  16. Miałem kiedyś problem z mapą wygenerowaną jako DXF z jakiegoś programu. Część obiektów (co dziwne nie wszystkie), było stworzone właśnie w ten sposób: pierwszy i ostatni punkt się pokrywały. Obiekty zamknięte. Stąd chcąc sprostać w maksymalny sposób porządkowi, trzeba rozważyć i taką możliwość. Sytuację gdzie jeden lub więcej segmentów się pokrywa, od początku należy potraktować jako błędną i obiektu takiego w ogóle nie rozważać. Tutaj ilustruję dane DXF dwóch przykładowych trójkątów (graficznie identycznych), o których mówię: Wynika z tego że trzeba sprawdzić czy ostatni i pierwszy wierzchołek nie pokrywają się. W zależności od wyniku obrać drogę: Albo poprawiamy, albo zostawiamy i uważamy że jest ok, albo ignorujemy. Co do zadania domowego: uproszczone czy nie, nie spełnia wymagań poprawnego rozwiązania...
  17. Zauważmy jednak że taki sam trójkąt możemy polilinią narysować na 2 sposoby: 1) Wskazując 3 punkty i zakończyć opcją zamknięcia. Wtedy ma 3 vertex-y i 3 segmenty 2) Wskazując 4 punkty (pierwszy i ostatni w tym samym punkcie) i dopiero zamknąć. Graficznie powstanie taki sam trójkąt, ale będzie miał 4 vertex-y, i 4 (ostatni zerowy) segmenty. Oba obiekty wyglądają tak samo, są jednak różne. Co do zadania domowego. Nie każdy czworobok jest prostokątem.
  18. Aby do końca doprowadzić sprawę poprawnego (do naszych celów) wyboru polilini, zauważmy jeszcze jeden przypadek. Oto bowiem wyobraźmy sobie polilinię zamkniętą składajacą się z dwóch segmentów łukowych. Niech to będzie księżyc (czy półksiężyc) na przykład. Do tej pory ograniczenia jakie nałożyliśmy to: polilinia zamknięta z trzema lub więcej segmentami. Musimy pochylić się nad ilością segmentów. Wychodzi na to że minimum trzy segmenty jest warunkiem koniecznym dla polilini składającej się segmentów prostoliniowych. Dla segmentów łukowych (choćby jeden łuk) bowiem, warunek spełniają już dwa segmenty. Jak tego dokonać w naszym Sel? Z pomocą przychodzi nam wiedza o budowie LWPOLYLINE, a w szczególności opis DXF wypukłości (bulge) czyli kody 42. Kody dotyczą opisu każdego wierzchołka, czyli w danych obietu występują wielokrotnie. Nie czas teraz opisywać szczegółowo co to jest bulge, teraz wystarczy nam wiedza że dla segmentów prostoliniowych kod 42 wynosi 0.0, dla łukowych zaś jest różny od 0.0. W istocie sprawdzenie czy dana polilinia składa się tylko z segmentów prostoliniowych, sprowadza się do sprawdzenia czy suma wszystkich kodów 42 jest równa zeru. Pamiętać należy także żeby bulge sprowadzić do liczb dodatnich (mogą być ujemne), tak aby nie zakłamać wyniku. Dla naszych celów przyda się także funkcja biblioteczna z CADPL-Pack'a, o nazwie cd:DXF_massoc, (całą bibliotekę można pobrać TU ) Funkcja zwraca listę wszystkich wartości zadanego kodu z listy DXF. I tak: jeśli d jest listą danych DXF obiektu, wywołanie: (cd:DXF_massoc 42 d) może zwrócić listę (np): (-0.517875 0.919164 0.0), teraz: (mapcar 'abs (cd:DXF_massoc 42 d)) zwraca: (0.517875 0.919164 0.0) a z: (apply '+ (mapcar 'abs (cd:DXF_massoc 42 d))) wynik będzie wynosił: 1.43704 Oczywiście dla polilini o zerowych bulge (segmenty prostoliniowe) - suma wszystkich zer, zwróci zero. I teraz mamy już naszą zmodyfikowaną funkcję Sel: (defun Sel (/ e d) (if (and (setq e (entsel "\nWskaż polilinię: ")) (= (cdr (assoc 0 (setq d (entget (car e))))) "LWPOLYLINE") (= 1 (logand 1 (cdr (assoc 70 d)))) (if (zerop (apply '+ (mapcar 'abs (cd:DXF_massoc 42 d)))) (>= (cdr (assoc 90 d)) 4) (>= (cdr (assoc 90 d)) 3) ) ) (princ "\nOk") (princ "\nŹle. ") ) ) Zadanie domowe: Napisać funkcję do wyboru polilinii będącej prostokątem... :)
  19. A teraz powinienem przybrać groźną minę i rzec, że oto podpuściłem was, a wy błędów nie widzicie... W rzeczywistości to sam go popełniłem. Chodzi o formę: (>= 4 (cdr (assoc 90 d))) bowiem powinno być: (>= (cdr (assoc 90 d)) 4) ponieważ porównanie "większe / równe niż" odnosi się do "prawej" strony, czyli do drugiego argumentu. W naszym przypadku ilość wierzchołków ma być równa lub większa niż 4, a nie odwrotnie. Prawda?
  20. Od końca. Ilość wierzchołków to jedyna wartość dla kodu 90. Stąd od razu porównanie. Dla zamknięcia sprawa jest bardziej złożona. Kod 70 zawiera jednocześnie informację czy polilinia jest zamknięta, oraz czy generowanie rodzaju linii jest włączone czy nie. I tak: 0 - poly otwarta a 1 zamknięta. PLINEGEN zaś to wartość 128. Stąd test zamknięcia polilinii sprowadza się do sprawdzenia logand = 1 (1 i 129 to zamknięta).
  21. Jeśli można tutaj (chyba że admin przeniesie do innego wątku), od samego początku. Czyli wybór obiektu. Niech będzie prosta funkcja o nazwie Sel do wyboru jednego obiektu. Do testowania zwracać będzie wynik Ok lub Źle. W kolejnych krokach trochę urośnie, ale pozwoli to prześledzić działanie. Podobnie jak w twoim kodzie, chcemy wybrać obiekt (polilinię). Spójrz: (defun Sel (/ e) (if (setq e (entsel "\nWskaż polilinię: ")) (princ "\nOk") (princ "\nŹle. ") ) )   Powiedzmy szczerze że żadnych rewelacji, nie trafisz - masz źle, wybierzesz jest Ok. Powiela twój błąd - możesz wybrać cokolwiek, a chcesz przecież polilinię. Zatem druga przymiarka: (defun Sel (/ e d) (if (and (setq e (entsel "\nWskaż polilinię: ")) (= (cdr (assoc 0 (setq d (entget (car e))))) "LWPOLYLINE") ) (princ "\nOk") (princ "\nŹle. ") ) ) W and od razu pobieramy dane obiektu (zmienna d), jednocześnie sprawdzamy czy to polilinia. Lepiej? Lepiej ale... w twoim przypadku trzeba wybrać polilinię zamkniętą raczej. Zatem popatrzmy: (defun Sel (/ e d) (if (and (setq e (entsel "\nWskaż polilinię: ")) (= (cdr (assoc 0 (setq d (entget (car e))))) "LWPOLYLINE") (= 1 (logand 1 (cdr (assoc 70 d)))) ) (princ "\nOk") (princ "\nŹle. ") ) ) and ma teraz trzy warunki ( 1.wybraliśmy obiekt, 2.polilinię i 3.zamkniętą). Zamknięta polilinia w DXF to kod 70. Musi mieć wartość 1 (oraz ewentualnie 129). Jest dużo lepiej. Ale to nie koniec. Właściwie, to powinieneś wybrać zamkniętą polilinię ale o co najmniej 3 segmentach... Więc zmieniamy sel: (defun Sel (/ e d) (if (and (setq e (entsel "\nWskaż polilinię: ")) (= (cdr (assoc 0 (setq d (entget (car e))))) "LWPOLYLINE") (= 1 (logand 1 (cdr (assoc 70 d)))) (>= 4 (cdr (assoc 90 d))) ) (princ "\nOk") (princ "\nŹle. ") ) ) I teraz mamy już bardziej (niż mniej) poprawny kawałek kodu do wybrania polilini...
  22. Nie wydaje mi się aby zabawy z obracaniem obiektów, będą efektywniejsze niźli LISP który wskazałem we wcześniejszym poście. Wykorzystuje on algorytm Grahama (wyznaczenie otoczenia punktów), sprowadzając wynik ostatecznie w uproszczeniu do najmniejszego prostokąta (o co w rzeczywistości chodzi). Wydaje mi się że działa dobrze w większości zastosowań.
  23. Co do znalezienia najmniejszego prostokąta (opisującego płaską figurę) zobacz tutaj: http://www.theswamp.org/index.php?topic=33607.msg389707#msg389707 Jest tam program do ściągnięcia: http://www.theswamp.org/index.php?action=dlattach;topic=33607.0;attach=15988 Potestuj i zobacz czy spełnia twoje oczekiwania. Co do lisp-ów zaś, zobacz tutaj: http://forum.cad.pl/cadpl-pack-v1-lsp-t78161.html To o takim zjawisku o nazwie CADPL-Pack. Jest to zestaw funkcji bibliotecznych, których użycie (także w twoim omawianym tutaj problemie), znacznie może ułatwić pracę. Również sama dyskusja przy poczęciu i rozwoju Pack-a, (w mojej opinii) może być źródłem porządnej lisp-owej wiedzy. W tej chwili widzę już na początku wiele błędów w twoim kodzie. Chętnie (w miarę możliwości czasowych) służę pomocą, w ich ewentualnej poprawie i wyjaśnieniu na czym polegają.
  24. Nie mieć jak u "starszego brata" wyboru tegoż?
  25. kojacek

    Rebus piątkowy

    Ok, to szybciej. 1) Rysuję wymiar kąta małego 2) Wybieram wymiar (z uchwytu wymiaru) szeregowy, wskazuję punkt 3) wymazuję wymiar z 1) (mały) :)