How to set view center point of viewport using Visual Lisp

During development of the ViewPortMaster, I faced the problem of, how to align viewports with defined frames in the model space. Most of the properties, like Height, Width, Insertion point, Scale, can be set with the put functions of VLA-Object ->> autodesk ActiveX resources. Unfortunately there is no property of the view center point. In this post I’m going to show you two different ways of how to manage it. First thought was, why not to use DXF codes with ordinary entget, entmod. Cool, according to autodesk DXF resources the view center point is exposed in group code 12 . Unfortunately it’s impossible to modify the viewport’s DXF codes, so I had to work around and I found that routine:

(setq paperObjects (vla-get-PaperSpace (vla-get-ActiveDocument (vlax-get-acad-object))))
(vlax-for x paperObjects
	(if (= (vla-get-ObjectName x) "AcDbViewport")
			(vla-put-DisplayLocked x :vlax-false)
			(vla-put-MSpace (vla-get-ActiveDocument (vlax-get-acad-object)) :vlax-true)
			(vla-put-ActivePViewport (vla-get-ActiveDocument (vlax-get-acad-object)) x)
				(vlax-3d-point vpC)
			(vla-put-MSpace (vla-get-ActiveDocument (vlax-get-acad-object)) :vlax-false)
			(vla-put-DisplayLocked x :vlax-true)

where: vpC – view center point e.g. ‘(0 100 0) The routine iterates over all VLA-Objects from current layout. When it finds AcDbViewport object it unlocks the viewport’s display, puts the model space and the viewport active and then sets the view center point vpC. It looks quite simple and works fine but that way also has some disadvantages. Synchronizing many viewports takes a long time, and what is more important, execution of it with the :vlr-LayoutSwitched reactor sometimes make errors.

Those two functions: vla-get-PaperSpace, vla-put-MSpace are problematic in AutoCad (in BricsCad/ZWcad works fine), so I had to find another way. I started digging into resources and voila! I found that forum thread: cadtutor thread. There is the editable xData named “ACAD” attached to the every viewport and it contains my Holy Grail 🙂 The xData cannot be modify by entmod but can be by ActiveX methods vla-GetXData; vla-PutXData. Let’s get xData from the viewport and look closer to values:

(setq vpObj (vlax-ename->vla-object (car entsel)))
(vla-GetXData vpObj "ACAD" 'XDataType 'XDataValue)

After extracting raw data from variant values we get:

nth XDataType XDataValue
0 1001 ACAD
1 1000 MVIEW
2 1002 {
3 1070 16
4 1010 0.0 0.0 0.0
5 1010 0.0 0.0 1.0
6 1040 0
7 1040 320
8 1040 131
9 1040 150
10 1040 50
11 1040 0
12 1040 0
13 1070 0
14 1070 1000
15 1070 1
16 1070 3
17 1070 0
18 1070 1
19 1070 0
20 1070 0
21 1040 0
22 1040 0
23 1040 0
24 1040 10
25 1040 10
26 1040 10
27 1040 10
28 1070 0
29 1002 {
30 1002 }
31 1002 }
Because most of the properties can be set with VisualLisp I will focus on the most important parts. Underlined rows are the Holy Grail 🙂 so 8 and 9 are X and Y coordinates of view center point in World UCS. Now we only need to change it as we want and put new xData to the object.
(vlax-safearray-put-element XDataValue 8 xCord)
(vlax-safearray-put-element XDataValue 9 yCord)
(vla-SetXData vpObj XDataType XDataValue)

xCord, yCord – real values

Looks simple, right? But there are two catches:

  1. If you’d like to change xData of any viewport in current layout, first you need to switch off that viewport’s display, and switch it on after you save the new xData to see the changes: (vla-put-ViewPortOn vpObj :vlax-false/:vlax-true)
  2. If you’d like to change xData of viewport which is not inserted in the current layout you don’t need to switch display on/off, but you need to remember to set system variable LAYOUTREGENCTL to 0 which controls caching of viewports in layouts. If you change the viewport’s xData, it’s cached and you switch layout to see the changes, you will not see any and additionally all xData changes will be lost.

That’s all about it. Most of the post’s content is quite easy to find in forums but I think it’s worth to put all together and make it public. In the next post I will explain how to find a proper 8th and 9th values of xData when the viewport is twisted, it took a while to find out :). Have a question? Leave a comment.

Leave a Reply

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