How to find view center point of twisted viewport

In the previous post I described how to set a view center point of the viewport. In this one I will try to explain how to find the right X, Y coordinates in World UCS in twisted viewports.

Let’s say we want to set view in the viewport twisted by 60° with view center point in X: 20, Y:15. Let’s apply below function.

(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
Model space
Model space
2015-10-28_20-25-03
Twisted viewport fails view center point
2015-10-28_20-25-37
Twisted viewport fails view center point

As you can see, despite setting desired X and Y coords of the view center point, it isn’t there. It turned out that the view defined in the viewport’s properties is rendered in the sequence:
 view center point → view twisting respect to the 0,0 in the World UCS → view displacement set in Target property

Below picture shows relationships between desired view center point and real center point rendered by autocad in the paper space.

Viewport twisting scheme
Viewport twisting schema

To find the proper values of X,Y coordinates to set in xData we need to rotate vector [0,0 _mpt] respect to 0,0 by the twist angle in opposite direction. Below picture shows what we need to do:

How to find the view center point
How to find the view center point

The mc-chVp routine finds the proper values of X,Y coords and save it in viewport’s xData that autocad will render desired view:

;--------------------------------------------------------------------------
;			M2Vpts - 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

Example of use:

(mc-chVp (car(entsel "\nPick viewport object:")) '(15 20) 60)

Function mc-chVp enumerates: distance vpCdist from 0,0 in World UCS to _mpt and angle vpCang between X axis and vector [0 _mpt]. Then it subtracts desired view twist angle _tw from vpCang and enumerates the proper X,Y coords to set in xData vpCalt as a result of polar function.

The result of the function
The result of the function

Leave a Reply

Your email address will not be published. Required fields are marked *