Jak znaleźć punkt centralny widoku obróconej rzutni
W poprzednim wpisie opisałem sposoby ustawienia centrum widoku wstawionej w arkuszu papieru rzutni. W tym opiszę jak znaleźć właściwe współrzędne X i Y w WCS (globalnym układzie współrzędnych) rzutni z obróconym widokiem.
Przyjmijmy, że potrzebujemy ustawić widok w rzutni obrócony o 60°
z centralnym punktem widoku we współrzędnych X: 20, Y:15
. Użyjmy poniższej funkcji:
(defun mc-setV ( / vp XDataType XDataValue)
(setq vp (vlax-ename->vla-object (car(entsel)))) ;pick viewpoport object
(vla-put-TwistAngle vp (* pi (/ -60.0 180.0))) ;put twist angle property in radians
(vla-put-ViewPortOn vp :vlax-false) ;turn off viewport
(vla-GetXData vp "ACAD" 'XDataType 'XDataValue) ;get xData "ACAD" from object
(vlax-safearray-put-element XDataValue 8 20) ;put X coord in the safe array
(vlax-safearray-put-element XDataValue 9 15) ;put Y coord in the safe array
(vla-SetXData vp XDataType XDataValue) ;set new xData values
(vla-put-ViewPortOn vp :vlax-true) ;turn on viewport
);defun
Jak widać, pomimo ustawienia docelowych współrzędnych X i Y centrum widoku rzutni, docelowy widok jest rozbieżny z naszymi oczekiwaniami. Okazuje się, że widok w rzutni jest tworzony wg poniższego schematu ustawień właściwości:
centrum widoku rzutni → obrót widoku względem punktu 0,0,0 WCS → przesunięcie widoku ustawione jako własność TARGET
Poniższy rysunek przedstawia zależności pomiędzy oczekiwanym centrum widoku rzutni (żółty) a wygenerowanym przez program (szary) w arkuszu papieru.
Aby znaleźć odpowiednie współrzędne X i Y do ustawienia w xData rzutni potrzebujemy obrócić wektor [0,0 _mpt]
względem punktu 0,0
o wartość kąta obrotu ale w przeciwnym kierunku. Poniższy rysunek pokazuje zależności geometryczne potrzebnych operacji:
Funkcja mc-chVp
znajduje właściwe współrzędne X i Y w zależności od zadanego kąta obrotu widoku, oraz ustawia te wartości dla wskazanej rzutni:
;--------------------------------------------------------------------------
; mc-chVp - function sets desired view center point and twist angle
; for picked viewport object
; _obj <ENAME or VLA-OBJECT> - viewport object to change
; _mpt <LIST OF REALS> - desired view center point
; _tw <REAL> - view rotation in degrees
;--------------------------------------------------------------------------
(defun mc-chVp ( _obj _mpt _tw / vpObj vpTwAng vpCang vpCdist vpCalt XDataType XDataValue doCont)
;validate picked object
(cond
((= (type _obj) 'ENAME)
(setq vpObj (vlax-ename->vla-object _obj)
doCont T
);setq
);ENAME
((= (type _obj) 'VLA-OBJECT)
(setq vpObj _obj
doCont T
);setq
);VLA-OBJECT
(T nil)
);cond
(if
(and
doCont
(= "AcDbViewport" (vla-Get-ObjectName vpObj))
);and
(progn
(setq vpTwAng (* pi (/ _tw 180.0)) ;DEG->RAD
vpCang (angle '(0 0) _mpt) ;angle between X axis and vector [(0,0) _mpt] in WORLD UCS
vpCdist (distance '(0 0) _mpt) ;distance between (0,0) and desired point (_mpt) in WORLD UCS
vpCalt (polar '(0 0) (- vpCang vpTwAng) vpCdist) ;proper view center point to set in object's xData
);setq
;set initial values of object's properties (target and direction) to make sure they won't disrupt
(vla-Put-Target vpObj (vlax-make-variant(vlax-safearray-fill (vlax-make-safearray vlax-vbDouble '(0 . 2)) '(0 0 0))))
(vla-Put-Direction vpObj (vlax-make-variant(vlax-safearray-fill (vlax-make-safearray vlax-vbDouble '(0 . 2)) '(0 0 1))))
(vla-put-ViewPortOn vpObj :vlax-false) ;turn off viewport's display
(vla-GetXData vpObj "ACAD" 'XDataType 'XDataValue) ;read "ACAD" xData from the object
(vlax-safearray-put-element XDataValue 8 (car vpCalt)) ;put X coordinate of view center point
(vlax-safearray-put-element XDataValue 9 (cadr vpCalt)) ;put Y coordinate of view center point
(vla-SetXData vpObj XDataType XDataValue) ;write new xData values to object
(vla-put-ViewPortOn vpObj :vlax-true) ;turn on viewport's display
);progn
;if error or not viewport object
(princ "\nAn error occurred or picked object is not AcDbViewport")
);if
);defun
Przykład użycia:
(mc-chVp (car(entsel "\nPick viewport object:")) '(15 20) 60)
Funkcja mc-chVp
oblicza:
odległość vpCdist
od 0,0 w WCS do _mpt
oraz kąt vpCang
pomiędzy osią X oraz wektorem [0 _mpt]
. Następnie odejmuje docelową wartość kąta obrotu _tw
od wartości vpCang
oraz oblicza docelowe wartości współrzędnych X,Y do ustawienia w xData vpCalt
jako wynik funkcji polar
.
Komentarze
Prześlij komentarz