Author Topic: AutoCAD LISP routine that moves objects based on the annotative scale  (Read 1180 times)

0 Members and 1 Guest are viewing this topic.

BKolbuszewski

  • Mosquito
  • Posts: 9
A little bit of background: I am creating a template for my team of drafters to use. We have a set of commonly used objects (les't call them "markers"), like section markers, leaders, dimensions, title blocks, etc. all set up in a table (not a real "Table", just arranged neatly in a rectangle). All of the markers are annotative, so that we do not need a separate set of markers for each os the scales that we work on.

Now we come to the problem: Although the markers, being annotative, scale properly when the annotation scale is changed, they all scale around their own basepoints (as they should). The problem is, that if these markers get too big due to the scale changes, they start to overlap so heavily, that they become totally unusable. I would like for them to move away from one another, so that they maintain their relative distances unchanged. In other words, I kinda want the whole table to behave like it is annotative. I know that it would be easy to solve by just making the whole table into an annotative block, but the markers need to be easily accessible for the drafters to use. I don't want them to have to explode the table-block each time they need to take a marker, or to have to go inside of this block, copy the markers they want, come out of the block and only then use them.

I tried to come up with a set of steps that would result in this behavior I want and this is what I think the LISP should do everytime the annotative scale is changed in the model space:

1. Get the centerpoint of the table border (which would itself be an annotative block, so that it properly encloses the "scaled-up" table in every scale).
2. Determine which objects are inside of the border (determine all the markers that are to be moved).
3. Measure the distance between this centerpoint of the border and the basepoints of all of the objects that are inside the border (the markers).
4. Scale this distance and move each marker in the same direction it is already "facing" with regard to the centerpoint, so that the new distance (in the new scale) is equal to this scaled distance. The scale factor of the distance would be based on the current and the new chosen scale (so if I was in 1:10 scale initially and change the scale to 1:1000, the distance grows by a factor of 100).
5. I don't want the LISP to prompt user for anything, it should run whenever the scale is changed, realise from which scale to which the change ocurred; and apply the position changes on the markers automatically.

Here's the link to an image showcasing the simplified version of the problem:
https://i.stack.imgur.com/RU70f.png
You can see the various markers inside of the orange table border. The border in the picture is selected, so that its basepoint is visible (I think it might be easiest to use this basepoint as the centerpoint around which the whole table "scales")

If anything is unclear or anyone needs additional info, please ask.

PS.
I should probably add that I know pretty much nothing about writing LISPS (or programming in general for that matter), so if You could be as explicit as You can in Your answers, I would really appriciate that.

I started to learn about AutoLISP and reactors in particular and I've written the following code as a start:

Code - Auto/Visual Lisp: [Select]
  1.   "CANNOSCALEVALUE"
  2.   '((:vlr-sysvarchanged . MoveMarkersOnScaleChange))
  3. )
  4.  
  5. (defun MoveMarkersOnScaleChange (calling-reactor :vlr-sysVarChanged)
  6.   (princ "Hello")
  7. )

From what I understand, this should simply print "Hello" in the command line each time the scale is changed (the CANNOSCALEVALUE variable changes). It kinda works like that, but I noticed that once the .lsp is loaded into my file, it starts to print "Hello" after pretty much everything I do (like draw a polyline, move something and so on), not only after the scale change (though that works as well). Sometimes it even prints in a rapid succession (HelloHelloHello, etc.). Could someone enlighten me as to what is going on here...?
I suspect it has something to do with the part(calling-reactor :vlr-sysVarChanged), cause this is the only part of the code I do not really get. And yes, I know that:

"Callback functions for all reactors, other than Object reactors, must be defined to accept two arguments:
The first argument identifies the Reactor object that called the function.
The second argument is a list of parameters set by AutoCAD.
"

but I do not really know what it means, so it's not much help.

I am attaching a dwg with a simplified version of my table. There are some markers in the table, a table border on a separate layer and made into an annotative block; and also some markers outside of the table. It is so that I know that the code I eventually come up with moves only the markers in the table, and leaves the other ones alone.
« Last Edit: July 24, 2023, 11:58:12 AM by BKolbuszewski »

BKolbuszewski

  • Mosquito
  • Posts: 9
Re: AutoCAD LISP routine that moves objects based on the annotative scale
« Reply #1 on: August 09, 2023, 08:38:25 AM »
If anyone is interested, I think I have solved the whole problem. The .lsp file is attached below. There is quite a lot of code that is not strictly necessary for the LISP to work (like test functions or sometimes funny comments), but I left it all in, since (as I am still a beginner) I want to be able to go back to this file often and be able to draw inspiration from it (see what worked, what didn't, why I finally did something the way I did, etc.). Of course I would still appreciate any optimizations or alternatives to my solutions.