Pomysł na lispa


Rekomendowane odpowiedzi

Dzień dobry.

Mam pewien pomysł na lispa. Niestety nie potrafię go samemu napisać.
Otóż:
1- tworzę z punktów 3D siatkę powierzchni 3DFace (http://paulbourke.net/papers/triangulate/Triangulator.LSP)
2- rysuję trasę (np. wodociągu, kanalizacji, drogi...) jako polilinię 2D (z=0)
;tu zaczyna się proponowany lisp
3- tymczasowo tworzę powierzchnie 3DFACE o z=0
   (https://forum.cad.info.pl/topic/1873-entmod-na-wielu-obiektach/)
4- znajduję punkty przecięcia z krawędziami powierzchni 3DFACE (punkty 2D)
   Nie wiem czy to pomoże, ale znalazłem coś takiego:
   (http://www.cadstudio.cz/freeware           Chodzi o plik:
   INTLINES - draws points in all intersections of selected objects, lines, incl. self-intersections (cdnc5-02.LSP by B.Kramer))
5- tworzę listę z długością polilinii 2D do tych punktów
   Np. tak: 
   

(vl-load-com)
(if (and (progn (prompt "\n Select Polyline :")
(setq e (ssget "_:s" '((0 . "*POLYLINE"))))
	         )
(setq p (getpoint "\n Specify point on the previous selected polyline :"))
)
(print (vlax-curve-getdistatpoint (ssname e 0) (vlax-curve-getclosestpointto (ssname e 0) p)))
)

6- rzutuję punkty 2D na powierzchnie 3DFACE. Pojawia się kilka pytań:

       na którą powierzchnię?

       odp: na powierzchnię, w której po spłaszczeniu (z=0) taki punkt się znajdzie (punkt wewnątrz trojkąta,a dokładnie na krawędzi): 

       (https://4programmers.net/Forum/Newbie/187154-program_sprawdzajacy_czy_punkt_nalezy_do_trojkata_)

       jak taki punkt zrzutować?

       odp: (https://forums.autodesk.com/t5/net/getting-the-point-of-intersection-between-plane-and-spline-3d/td-p/5812328)

    7 - odczytuję współrzędne Z utworzonych punktów 3D


 

Mając odległości (pkt 5) i rzędne (pkt 7) można narysować profil po terenie istniejącym :)

Pozdrawiam

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

Temat wydaje się ciekawy, niestety raczej nie będziemy w stanie opracować "wszystkomającego" lispa za jednym zamachem.

Chętnie pomożemy ale proszę się zastanowić nad podzieleniem jednego dużego skryptu na większą liczbę małych funkcji.

Tym bardziej, że zagadnienie jest nieco zawiłe i można "pójść w złym kierunku".

 

Odnośnik do komentarza
Udostępnij na innych stronach

Wydaje mi się że łatwiej coś by można podpowiedzieć jeśli autor umieściłby jakieś szkice. Może DWG z wykonanym krokiem 1 oraz screen lub drugi DWG z tym co ma byc na końcu (krok 7) .

J.

 

 

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

20 godzin temu, Pawcyk napisał:

Dzień dobry.

2- rysuję trasę (np. wodociągu, kanalizacji, drogi...) jako polilinię 2D (z=0)
;tu zaczyna się proponowany lisp

Pozdrawiam

Spostrzeżenia:

1. Jeśli w pkt 1 mamy już siatkę (np. triangulacyjną) to w pkt 2 zamiast używania polilinii 2d lepiej użyć polilinii 3d (3dPoly) wtedy problem właściwie sam się rozwiązuje gdy zadbamy by snap polilinii łapał także współrzedną 'z'  najbliższego 3DFace. Stworzenie rozciągniętej kopii tej polilinii (jako profil) to już banalne zadanie. 

2. Duża mapa to setki 3dFace. Jeśli chcesz porządny skrypt zrobić to znacznie bardziej skuteczne będzie uzycie zamiast n*3dFace obiektów PolygonMesh lub PolyfaceMesh lepiej przystosowanychdo pracy jako siatka terenu z elewacją.

3. W Zwcad2017 jest polecenie gein ( import z Google Earth) . Prawdopodobnie importuje płaskie zdjęcia (bez elewacji) ale jako podklad graficzny terenu byłby przydatny w całości takiego projektu do dokumentacji. 

J. 

Odnośnik do komentarza
Udostępnij na innych stronach

1 godzinę temu, JasW napisał:

Spostrzeżenia:

1. Jeśli w pkt 1 mamy już siatkę (np. triangulacyjną) to w pkt 2 zamiast używania polilinii 2d lepiej użyć polilinii 3d (3dPoly) wtedy problem właściwie sam się rozwiązuje gdy zadbamy by snap polilinii łapał także współrzedną 'z'  najbliższego 3DFace. Stworzenie rozciągniętej kopii tej polilinii (jako profil) to już banalne zadanie. 

2. Duża mapa to setki 3DFace. Jeśli chcesz porządny skrypt zrobić to znacznie bardziej skuteczne będzie uzycie zamiast n*3dFace obiektów PolygonMesh lub PolyfaceMesh lepiej przystosowanychdo pracy jako siatka terenu z elewacją.

3. W Zwcad2017 jest polecenie gein ( import z Google Earth) . Prawdopodobnie importuje płaskie zdjęcia (bez elewacji) ale jako podklad graficzny terenu byłby przydatny w całości takiego projektu do dokumentacji. 

J. 

Ad 1. Pojawia się problem z łukami. Po drugie jak narysować polilinię 3d  idealnie prostą w płaszczyźnie 2D?

Ad 2. Przyznam się że nie zastanawiałem się nad zastosowaniem innych rzeczy niż 3DFace. Można również narysować zwykłe trójkąty z 3DPOLY (program do triangulacji tworzy 3DFACE)

2 godziny temu, kruszynski napisał:

NIe sprawdzałem na żywym przykładzie, ale teoretycznie punkty przecięcia 3DFace z polilinią może się udać uzyskać tak:


(vlax-invoke-method powierzchnia 'IntersectWith oś acExtendNone )

 

A co do tworzenia punktów wygrzebałem coś takiego:

http://www.lee-mac.com/intersectionfunctions.html

co daje taki efekt:

;; Intersections  -  Lee Mac
;; Returns a list of all points of intersection between two objects
;; for the given intersection mode.
;; ob1,ob2 - [vla] VLA-Objects
;;     mod - [int] acextendoption enum of intersectwith method

(defun LM:intersections ( ob1 ob2 mod / lst rtn )
    (if (and (vlax-method-applicable-p ob1 'intersectwith)
             (vlax-method-applicable-p ob2 'intersectwith)
             (setq lst (vlax-invoke ob1 'intersectwith ob2 mod))
        )
        (repeat (/ (length lst) 3)
            (setq rtn (cons (list (car lst) (cadr lst) (caddr lst)) rtn)
                  lst (cdddr lst)
            )
        )
    )
    (reverse rtn)
)

;; Intersections Between Sets  -  Lee Mac
;; Returns a list of all points of intersection between objects in two selection sets.
;; ss1,ss2 - [sel] Selection sets

(defun LM:intersectionsbetweensets ( ss1 ss2 / id1 id2 ob1 ob2 rtn )
    (repeat (setq id1 (sslength ss1))
        (setq ob1 (vlax-ename->vla-object (ssname ss1 (setq id1 (1- id1)))))
        (repeat (setq id2 (sslength ss2))
            (setq ob2 (vlax-ename->vla-object (ssname ss2 (setq id2 (1- id2))))
                  rtn (cons (LM:intersections ob1 ob2 acextendnone) rtn)
            )
        )
    )
    (apply 'append (reverse rtn))
)

(defun c:intersets ( / ss1 ss2 )
    (if (and (setq ss1 (ssget))
             (setq ss2 (ssget))
        )
        (foreach pnt (LM:intersectionsbetweensets ss1 ss2)
            (entmake (list '(0 . "POINT") (cons 10 pnt)))
        )
    )
    (princ)
)
(vl-load-com) (princ)

...i działa. Chociaż wolałbym jedną linijkę kodu...

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

Punkt 4 odhaczony. Punkt 5 również da radę zrobić.
Czas na 6, czyli z listy wszystkich 3DFace wybrać tę powierzchnię, która spełnia warunek:
https://4programmers.net/Forum/Newbie/187154-program_sprawdzajacy_czy_punkt_nalezy_do_trojkata_

Wcześniej pisałem, że trzeba "spłaszczyć" 3DFace, ale wystarczy do sprawdzenia brać tylko współrzędne x i y wierzchołków. 

Pozdrawiam

Odnośnik do komentarza
Udostępnij na innych stronach

Zdaje się, że wyważamy otwarte drzwi...
https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/to-get-intersection-between-a-line-and-a-3dface/td-p/2745633/page/3

;lisp by Marko_Ribar
(defun _ilt ( p1 p2 t1 t2 t3 / v^v unit Coplanar-p ptinsidetriangle-p ptontriangle-p ptonline-p _ilp nor o )

  (defun v^v ( u v )
    (list
      (- (* (cadr u) (caddr v)) (* (cadr v) (caddr u)))
      (- (* (car  v) (caddr u)) (* (car  u) (caddr v)))
      (- (* (car  u) (cadr  v)) (* (car  v) (cadr  u)))
    )
  )

  (defun unit ( v )
    (mapcar '(lambda ( x ) (/ x (distance '(0.0 0.0 0.0) v))) v)
  )
  
  (defun Coplanar-p ( p1 p2 p3 p4 )
    (
      (lambda ( n1 n2 )
        (equal (v^v n1 n2) '(0.0 0.0 0.0) 1e-8)
      )
      (v^v (mapcar '- p1 p2) (mapcar '- p1 p3))
      (v^v (mapcar '- p1 p2) (mapcar '- p1 p4))
    )
  )

  (defun ptinsidetriangle-p ( pt p1 p2 p3 )
    (if
      (and
        (Coplanar-p pt p1 p2 p3)
        (not
          (or
            (inters pt p1 p2 p3)
            (inters pt p2 p1 p3)
            (inters pt p3 p1 p2)
          )
        )
        (not
          (or
            (> (+ (distance pt p1) (distance pt p2)) (+ (distance p3 p1) (distance p3 p2)))
            (> (+ (distance pt p2) (distance pt p3)) (+ (distance p1 p2) (distance p1 p3)))
            (> (+ (distance pt p3) (distance pt p1)) (+ (distance p2 p3) (distance p2 p1)))
          )
        )
      )
      T
      nil
    )
  )

  (defun ptontriangle-p ( pt p1 p2 p3 )
    (if
      (or
        (equal (distance p1 p2) (+ (distance pt p1) (distance pt p2)) 1e-7)
        (equal (distance p2 p3) (+ (distance pt p2) (distance pt p3)) 1e-7)
        (equal (distance p1 p3) (+ (distance pt p1) (distance pt p3)) 1e-7)
      )
      T
      nil
    )
  )

  (defun ptonline-p ( pt p1 p2 )
    (equal (distance p1 p2) (+ (distance pt p1) (distance pt p2)) 1e-7)
  )

  (defun _ilp ( p1 p2 o nor / p1p p2p op tp pp p )
    (if (not (equal (v^v nor (unit (mapcar '- p2 p1))) '(0.0 0.0 0.0) 1e-7))
      (progn
        (setq p1p (trans p1 0 (v^v nor (unit (mapcar '- p2 p1))))
              p2p (trans p2 0 (v^v nor (unit (mapcar '- p2 p1))))
              op  (trans o 0 (v^v nor (unit (mapcar '- p2 p1))))
              op  (list (car op) (cadr op) (caddr p1p))
              tp  (polar op (+ (* 0.5 pi) (angle '(0.0 0.0 0.0) (trans nor 0 (v^v nor (unit (mapcar '- p2 p1)))))) 1.0)
        )
        (if (inters p1p p2p op tp nil)
          (progn
            (setq p (trans (inters p1p p2p op tp nil) (v^v nor (unit (mapcar '- p2 p1))) 0))
            p
          )
          nil
        )
      )
      (progn
        (setq pp (list (car (trans p1 0 nor)) (cadr (trans p1 0 nor)) (caddr (trans o 0 nor))))
        (setq p (trans pp nor 0))
        p
      )
    )
  )

  (setq nor (unit (v^v (mapcar '- t3 t1) (mapcar '- t2 t1))))
  (setq o t1)
  
  (if (_ilp p1 p2 o nor)
    (if 
      (and
        (or
          (ptinsidetriangle-p (_ilp p1 p2 o nor) t1 t2 t3)
          (ptontriangle-p (_ilp p1 p2 o nor) t1 t2 t3)
        )
        (ptonline-p (_ilp p1 p2 o nor) p1 p2)
      )
      (_ilp p1 p2 o nor)
      nil
    )
    nil
  )
)

(defun c:bum ()
(setq P100 (getpoint))
(setq P101 (getpoint))
(setq T100 (getpoint))
(setq T101 (getpoint))
(setq T102 (getpoint))
(_ilt P100 P101 T100 T101 T102)
);Koniec test

 

Odnośnik do komentarza
Udostępnij na innych stronach

Jeżeli można to wróciłbym do punktu 3 i 4.
Otóż zastanawiam się na koniecznością tworzenia zrzutowanych 3DFace do poziomu zero. Może w kodzie ze str.
http://www.lee-mac.com/intersectionfunctions.htm (zaproponowanym kilka postów wyżej) linijkę:
(setq rtn (cons (list (car lst) (cadr lst) (caddr lst)) rtn)
wystarczy zamienić na:  
(setq rtn (cons (list (car lst) (cadr lst) 0) rtn)

Oczywiście nie wystarczy ..bo nie tworzy w ten sposób "wirtualnych" punktów przecięcia.

Idea jest taka aby program brał współrzędne powierzchni x, y, a za "z" podstawiał 0. W ten sposób odpadnie konieczność tworzenia płaskich 3DFACE. 

 

 

Odnośnik do komentarza
Udostępnij na innych stronach

Próbuję coś tam pisać, ale ze względu na ograniczony wolny czas idzie mi to powoli.
Natrafiłem na problem. Poniższy kod raz rzutuje punkt, a raz wyrzuca błąd. 

;;
;;PONIEWAŻ 3DFace POSIADA 4 WIERZCHOLKI (2 TAKIE SAME) NALEŻY USUNĄĆ DUPLIKUJĄCE SIĘ ELEMENTY
;;
;; Unique  -  Lee Mac
;; Returns a list with duplicate elements removed.
;;
(defun remove_doubles  (lst /)
(vl-load-com)
  (if lst
    (cons (car lst) (remove_doubles (vl-remove (car lst) lst)))))
;;
;;
(defun c:bum ()
(print "wskaż powierzchnie")
(setq ssSelections (ssget))
(print "wskaż punkt")
(setq Point (getpoint))
(setq Point2 (list	(nth 0 Point) ; Point i Point2 tworzy linię pionową o wys 500
					(nth 1 Point)
					500))
(repeat	(setq	intCount (sslength ssSelections))
		(setq	intCount     (1- intCount)
				entSelection (ssname ssSelections intCount)
				lstEntity    (entget entSelection))
		;Wierzchołki 3DFACE 
		(setq P10 	(list 	(nth 1 (assoc 10 lstEntity))
							(nth 2 (assoc 10 lstEntity))
							(nth 3 (assoc 10 lstEntity)) )
			  P11	(list 	(nth 1 (assoc 11 lstEntity))
							(nth 2 (assoc 11 lstEntity))
							(nth 3 (assoc 11 lstEntity)) )
			  P12	(list 	(nth 1 (assoc 12 lstEntity))
							(nth 2 (assoc 12 lstEntity))
							(nth 3 (assoc 12 lstEntity)) )
			  P13	(list 	(nth 1 (assoc 13 lstEntity))
							(nth 2 (assoc 13 lstEntity))
							(nth 3 (assoc 13 lstEntity)) ))
	;Lista wierzchołków z jednym (zdublowanym) usuniętym
	(setq ListVtx	(remove_doubles (list P10 P11 P12 P13) ))
	;Pozostałe 3 wierzchołki trójkąta
	(setq P100 (nth 0 ListVtx)
		  P101 (nth 1 ListVtx)
		  P102 (nth 2 ListVtx))
;tworzenie punktu przecięcia linii (point, Point2) i trójkąta (P100 P101 P102)
(entmake (list '(0 . "POINT") (cons 10 (_ilt Point Point2 P100 P101 P102)) ))
);end repeat

);koniec bum	

UWAGA: kod funkcji _ilt jest zamieszczony wyżej.
...a i jeszcze jeden problem. jeżeli punkt 2D (który rzutujemy) trafia na krawędź 2 trójkątów to program tworzy 2 punkty. Jak to obejść?

Pozdrawiam  

Odnośnik do komentarza
Udostępnij na innych stronach

Dnia 29.03.2017 o 14:14, Pawcyk napisał:

Natrafiłem na problem. Poniższy kod raz rzutuje punkt, a raz wyrzuca błąd. 

może Pan coś więcej powiedzieć na temat tego błędu? np komunikat błędu jaki się pojawia?

sprawdzałem na stworzonym przez siebie przykładzie i komunikat jaki otrzymuję jest:

Error: incorrect type - nil

Jest to spowodowane tym, że _ilt czasem zwraca nil, a w pętli jest

(entmake (list '(0 . "POINT") (cons 10 (_ilt Point Point2 P100 P101 P102)) ))

Jesli _ilt zwróci nil, to gdzie entmake ma wstawić punkt?

Najłatwiej to ogarnąć tak:

(setq iltresult (_ilt Point Point2 P100 P101 P102 ) )
(if (not (null  iltresult)) (progn
	(entmake (list '(0 . "POINT") (cons 10 iltresult ) ))
)

 

Dnia 29.03.2017 o 14:14, Pawcyk napisał:

...a i jeszcze jeden problem. jeżeli punkt 2D (który rzutujemy) trafia na krawędź 2 trójkątów to program tworzy 2 punkty. Jak to obejść?

Na rozwiązanie tego tematu może być wiele pomysłów, ja proponuję taki, żeby w funkcji tworzyć listę punktów. następnie usunąć z niej duplikaty, a na końcu rysować punkty z przeczyszczonej listy.

Samo usuwanie duplikatów może spowodować niespodzianki jeśli użyje Pan do porównania operatora =. do porównywania punktów lepiej jest użyć np

(> (distance p1 p2 ) 0.0001)

albo:

(equal p1 p2 0.0001 )


 

Odnośnik do komentarza
Udostępnij na innych stronach

  • 2 tygodnie później...
  • 1 miesiąc temu...

Wczoraj znalazłem taki program, niestety działa na wersji ZW2015+  http://www.glamsen.se/CadTools.htm

jest praktycznie za darmo. Generalnie jest pod drogi, ale można utworzyć teren, siatkę, warstwice na podstawie pkt.PL3D przekroje, profil, powierzanie wykopu i nasypu.  Ma nawet funkcję konwersji tekstu na rzędną Z .

 

 

Odnośnik do komentarza
Udostępnij na innych stronach

  • 2 miesiące temu...
  • 2 tygodnie później...

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