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
rys.1 Obszar modelu
rys. 2 Niedopasowanie po obrocie
rys. 3 Niedopasowanie po obrocie

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.

rys. 4 Układ geometryczny rzutni po jej obrocie

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:

rys. 5 Jak znaleźć właściwy centralny punkt widoku po obrocie rzutni

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.

rys. 6 Efekt działania funkcji

Komentarze

Popularne posty z tego bloga

Nowe wydanie u-View 1.0 - dawny ViewPortMaster

Jak ustawić skalę opisową rzutni poprzez VisualLisp

Jak zmienić centrum widoku rzutni w obszarze papieru