Line length determines linetype scale

Line length determines linetype scale

Anonymous
Not applicable
4,140 Views
22 Replies
Message 1 of 23

Line length determines linetype scale

Anonymous
Not applicable

Hello again everyone,

Sorry to take advantage of all the talented members here by asking another question so soon but this one's been bugging me for a while.

My firm works exclusively in model space and without any sort of annotation related scaling etc.  On floor plans we use one of the standard ACAD dashed lines to show the lintels over the windows.  We have a linetype and layer (LintelNew) set up to do this.  This linetype basically displays as a long dash, gap, short dash, gap, long dash.  So there's three segments per line.  Looks sort of like this: (--------    ----     --------).

My issue is that in order to get the dashed line style to look like that, with only three segments showing, I need to change the linetype scale via the properties panel as each lintel is a different length (for different window sizes).  For example, to get that line to show as desired on a short lintel, its linetype scale might need to be .3, where a larger lintel will require .9.

I cannot make any sorts of global changes as it is only these specific lines that need tweaking; they're the only lines where we ever change the scale.  Selecting them one by one and doing it in the properties is a major pain and involves a lot of guessing and checking.

I am wondering if anyone might know of a way where the line length and linetype scale could be related..?  For example, the linetype scale is connected to or driven by the length of the line?  To put it another way, the scale becomes a percentage of the line length.

As I am typing this I'm also realising that I would only ever want this to happen when drawing lintels and on that specific 'lintel' layer.  I dont want that scaling effect in action for every line I draw.

Not sure if this is even possible so please ignore if I'm asking the impossible here.

 

Thanks for reading everyone.

 

Brad

 

0 Likes
Accepted solutions (2)
4,141 Views
22 Replies
Replies (22)
Message 2 of 23

ВeekeeCZ
Consultant
Consultant

Well, I think this kind of calculation would certainly be possible (Autocad must calculate that somehow), but very complicated. 

 

What I can imagine is a tool, that will apply a linetype scale by the given table.

EG

all lines in lintel layer (lt lintelnew is a layer property?)

0<len<=0.3 set lt scale 0.3

0.3<len<=1 set lt scale 0.8

1<len set lt scale 1

that could be applied to all, or by window selection.

0 Likes
Message 3 of 23

cadffm
Consultant
Consultant

@Anonymous 

Also possible by a factor (plus something special distance  for the Start and endpoint),

but if you talking about LINEs ONLY,

why not a dynamic Block for this?

 

Can you upload some samples for us? A DWG with your daily work..

(and tell us the name of this linetyle you talking about)

Sebastian

0 Likes
Message 4 of 23

Anonymous
Not applicable

Thank-you so very much BeeKeeCZ. I'm showing my ignorance as I what you've suggested didn't even occur to me; I had no idea where to start. Genuinely appreciate your swift & very helpful reply.

Hopefully someone out there can shape what you've provided into an actual structured program or routine. You've provided the bones but I'm still not fully sure how to apply it yet.

Thanks again.

0 Likes
Message 5 of 23

Anonymous
Not applicable

Thankyou CADffm.

Very new to using LISP routines I'm sorry so not entirely sure I understand what you mean. I will provide a screen grab or two when I'm at work tomorrow if you're still interested in contributing. 

I'm the meantime however, could you expand in simple terms how making the lintel/s a dynamic block might solve the issue.

Really do appreciate your willingness to share & teach.

0 Likes
Message 6 of 23

ВeekeeCZ
Consultant
Consultant

Here you have something to start with

(defun c:LintelScale ( / ss i ent len)

  (if (setq s (ssget '((0 . "LINE") (8 . "LINTEL"))))
    (repeat (setq i (sslength s))
      (if (setq e (ssname s (setq i (1- i)))
		l (getpropertyvalue e "Length"))
	(setpropertyvalue e "LinetypeScale" (cond ((<= l 0.3) 	0.3) 
						  ((<= l 1.) 	0.8)
						  (1))))))
  (princ)
  )

 

Or possibly add "X" into the ssget to select them all automatically, look HERE  for more details.

0 Likes
Message 7 of 23

Anonymous
Not applicable

You guys & this forum are unbelievable! I don't know whether to share this with my workmates or keep it to myself & just show off by crushing time taken to do jobs.

BeeKeeCZ you've been so good to me I hate to ask but could you please explain (just briefly) that last line of:

(cond ((<= l 0.3) 0.3) ((<= l 1.) 0.8) (1))))))

Eg. Which numbers I would modify & how/why?

I'm sorry I need to be carried through work you find simple & mundane. Its a game changer for me though if it helps!

0 Likes
Message 8 of 23

ВeekeeCZ
Consultant
Consultant
Accepted solution

It's the same table as is in msg #2.

It takes the first one that is True.

0 Likes
Message 9 of 23

Anonymous
Not applicable

So it is.My bad. Can't wait to get to work tomorrow & put it into action. Having to do this, line by line, every line a manual property change was a very popular moan amongst everyone in the office.

I owe you a beer mate. Thank-you so very much.

Message 10 of 23

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... we use one of the standard ACAD dashed lines to show the lintels ....

Looks sort of like this: (--------    ----     --------).

....


I would think a simpler multiple of the Line length could be applied, rather than have a limited number of length classes.  [In @ВeekeeCZ's suggestion, beyond a certain length you'll get more than your limit of 3 dashes.]  But first:

That "image" looks more like a CENTER-family linetype than one of the DASHED kinds.  In DASHED linetypes at a length & linetype combination to show 3 dashes, the middle one is longer  than the end ones, except when you get right up close to the length where it goes to 4 dashes [top one here], and then it's barely shorter:
3Dashes.JPG

[That's DASHED at Linetype Scale of 1, in 0.1-unit length increments; anything shorter goes to 2 dashes, anything longer goes to 4.]

But CENTER looks more like it:

3Center.JPG

[in which case anything shorter goes to continuous, and anything longer to 5 dashes.]  A gradually incremented linetype scale would make the proportions toward the top more like the bottom ones, if that's the "look" you want.

 

Which do you really use?  And is it from the Imperial acad.lin or the Metric acadiso.lin?  Also, is your LTSCALE setting always 1?

Kent Cooper, AIA
0 Likes
Message 11 of 23

Anonymous
Not applicable

So sorry to pester you again but am having as little trouble here.  Your code works fine if I change the two values provided in your example but it fails when I start to add my own underneath that.  Have listed the window widths/sizes and required linetype scale below if you could share some more hints..?

 

300 - 0.1

600 - 0.2

900 - 0.3

1200 - 0.4

1500 - 0.5

1800 - 0.6

2100 - 0.7

2400 - 0.8

2700 - 0.9

3000 - 1.0

0 Likes
Message 12 of 23

Anonymous
Not applicable

Please ignore the above request.  Worked it out.  Works a charm.  Thank you so much

Message 13 of 23

Anonymous
Not applicable

Hello again everyone,

 

I managed to use BeekeeCZ's solution of:

(defun c:LintelScale ( / ss i ent len)

  (if (setq s (ssget '((0 . "LINE") (8 . "LINTEL"))))
    (repeat (setq i (sslength s))
      (if (setq e (ssname s (setq i (1- i)))
		l (getpropertyvalue e "Length"))
	(setpropertyvalue e "LinetypeScale" (cond ((<= l 0.3) 	0.3) 
						  ((<= l 1.) 	0.8)
						  (1))))))
  (princ)
  )

But then modified it to try and include some of the lintel/window sizes we use.  My new code looks like the following:

 

(defun c:LSCALE ( / ss i ent len)

(if (setq s (ssget '((0 . "LINE") (8 . "LINTEL-NEW"))))
(repeat (setq i (sslength s))
(if (setq e (ssname s (setq i (1- i)))
l (getpropertyvalue e "Length"))
(setpropertyvalue e "LinetypeScale" (cond ((<= l 300) 0.1)
((<= l 600) 0.2)
((<= l 900) 0.3)
((<= l 1200) 0.4)
((<= l 1500) 0.5)
((<= l 1800) 0.6)
((<= l 2100) 0.7)
((<= l 2400) 0.8)
((<= l 2700) 0.9)
((<= l 3000) 1)

(1))))))
(princ)
)

 

This works fine, as expected for the exact numbers in the list above but if I draw a line say...2550 long, running the lisp routine on it fails to do anything.  My very limited knowledge of coding suggsts to me that the ((<= l 2700) 0.9) line of code meant "anything equal to or less than 2700 gets its linetype scale changed to 0.9)..?

 

Its not practical to list every single window size and even if I could/did, if the draftsperson before me was just one millimeter off then my lisp wont work.  Is anyone able to explain whats happening here and what I need to do to use a range of numbers instead of exact values?  For example ((<= l 2650 - 2700) 0.9)?

 

Many thanks in advance

0 Likes
Message 14 of 23

Kent1Cooper
Consultant
Consultant

Do the linetype scales need to be in multiples of 0.1?  Can you do something as simple as this?

 

(setpropertyvalue e "LinetypeScale" (/ l 3000))

 

No need for the (cond), or the "categories" of length, and no going to four dashes if you happen to occasionally do one significantly longer than your usual categories.

Kent Cooper, AIA
0 Likes
Message 15 of 23

Anonymous
Not applicable

Hi Kent,

 

Thank you for your time.

I'm obviously missing something here because so fas as I can tell, editing the code as per your suggestion results only in changing the linetype scale of every line to 1.0.  Shorter lines like anything under 2600mm require scales less than one in order to get the three segments to show.  Longer lines like 6000mm and above need a scale greater than one to make sure the line has only three segments.  If it helps, the LINTEL-NEW layer is using the CENTER2 linetype from standard AutoCad lines.

I've probably adjusted my code incorrectly.  It looks like this now:

 

(defun c:LSCALE ( / ss i ent len)

(if (setq s (ssget '((0 . "LINE") (8 . "LINTEL-NEW"))))
(repeat (setq i (sslength s))
(if (setq e (ssname s (setq i (1- i)))
l (getpropertyvalue e "Length"))
(setpropertyvalue e "LinetypeScale" (/ l 3000))


(1))))))
(princ)
)

 

I'm frustratingly new to all of this so maybe if you could add your suggestion and provide me the entire code snippet..?

 

Many thanks Kent

0 Likes
Message 16 of 23

ВeekeeCZ
Consultant
Consultant
Accepted solution

@Anonymous wrote:

(defun c:LSCALE ( / s i e l) ; fixed - not coursing any error

(if (setq s (ssget '((0 . "LINE") (8 . "LINTEL-NEW"))))
(repeat (setq i (sslength s))
(if (setq e (ssname s (setq i (1- i)))
l (getpropertyvalue e "Length"))
(setpropertyvalue e "LinetypeScale" (cond ((<= l 300) 0.1)
((<= l 600) 0.2)
((<= l 900) 0.3)
((<= l 1200) 0.4)
((<= l 1500) 0.5)
((<= l 1800) 0.6)
((<= l 2100) 0.7)
((<= l 2400) 0.8)
((<= l 2700) 0.9)
((<= l 3000) 1) ; this line is redundant but does no harm. It's already covered by the line below. 

(1))))))
(princ)
)

; NO ERROR in the code. The code should work OK.

 

This works fine, as expected for the exact numbers in the list above but if I draw a line say...2550 long, running the lisp routine on it fails to do anything.  My very limited knowledge of coding suggsts to me that the ((<= l 2700) 0.9) line of code meant "anything equal to or less than 2700 gets its linetype scale changed to 0.9)..? TRUE. If the line is in your 'lintel-new' layer unlocked, it should work as described. It works like the to me.

 

Its not practical to list every single window size and even if I could/did, if the draftsperson before me was just one millimeter off then my lisp wont work.  Is anyone able to explain whats happening here and what I need to do to use a range of numbers instead of exact values?  For example ((<= l 2650 - 2700) 0.9)? No. The lower limit is given by all the previous conditions. The secret of the cond is that IF the certain condition is TRUE, then COND is done (all below conditions are not even tested). So let say L is 1150. It goes: is L less or equal to 600? - no; is L <= 900? - no; is L <= 1200? - yes, take 0.4. Done. Go (princ) line in this case.

 

 


 

BTW here is Kent's fixed version:

(defun c:LSCALE ( / s i e l)
  
  (if (setq s (ssget '((0 . "LINE") (8 . "LINTEL-NEW"))))  ; this if filter for LINE in layer "LINTEL-NEW". all else is filtered out.
    (repeat (setq i (sslength s))
      (if (setq e (ssname s (setq i (1- i)))
		l (getpropertyvalue e "Length"))
	(setpropertyvalue e "LinetypeScale" (/ l 3000)))))
  (princ)
  )

 

0 Likes
Message 17 of 23

Anonymous
Not applicable

Massive thankyou to yourself and Kent.  Everything working perfectly.

 

I most sincerely appreciate your patience with me and perseverance.  Your knowledge of this stuff is amazing and daunting!

 

All the best guys.

0 Likes
Message 18 of 23

Sea-Haven
Mentor
Mentor

Just a dumb idea lisp has a little problem with reals and integers 2 is not 2.0 so try your cond with .0 added so it compares at a real level. This may fix the 2000.1 problem.

0 Likes
Message 19 of 23

Anonymous
Not applicable

I wasn't aware of that & it would have stumped me had that occurred when using my new lisp routine. Many thanks for the heads up friend 

0 Likes
Message 20 of 23

Kent1Cooper
Consultant
Consultant

@Sea-Haven wrote:

Just a dumb idea lisp has a little problem with reals and integers 2 is not 2.0 so try your cond with .0 added so it compares at a real level. This may fix the 2000.1 problem.


 

I don't think that can be an issue here.  The "little problem with reals and integers" occurs only when dividing -- if you divide an integer by an integer, you get an integer result, dropping any remainder, so when a (/) function is involved, and you don't want the remainder ignored, at least one of the numbers [not both] needs to be a real number.  But a comparison like these should not be affected.

Kent Cooper, AIA
0 Likes