Hi,
I need to segregate closed polylines in my drawing by area range. Ideally, I would input the number of ranges I need.
Then somehow find the smallest and largest pline area to determine the range values (rounding up to a sensble number)
Then with the ranges determined the polylines would be segregated and moved to new layers.
I've been trying to hobble together pieces but with no joy.
Can someone set me going with the correct approach, I'd appreciate it.
Regards
Sean
Solved! Go to Solution.
Solved by Kent1Cooper. Go to Solution.
Solved by pbejse. Go to Solution.
Solved by Kent1Cooper. Go to Solution.
Hello from France
I have this kind of VLisp routine to sort PLines by Length or by Area since many years ...
I am not at all a developper so I can't update or improve it !
I have translated the minimum (from French to US) ...
IMPORTANT : You must update the source with YOURS Min-Max Values HERE >>>
(cons 1 3)
(cons 3 10)
(cons 10 20)
(cons 20 50)
(cons 50 200)
In this routine today, all Plines (if concerned by the famous Min-Max Values)
will changed from original Layer to a NEW layer named :
"ZZZ_SURF_LONG-1_3"
"ZZZ_SURF_LONG-3_10"
etc ...
Please enjoy, Bye, Pat
Patrice BRAUD
@sean.keohane wrote:Hi,
I would input the number of ranges I need.
Then somehow find the smallest and largest pline area to determine the range values (rounding up to a sensble number)
Then with the ranges determined the polylines would be segregated and moved to new layers.
Sean
Input number of ranges: <type in the value here as an example>
and what will the result if there are 5 items found Lets say 502.36 is the largest and 45.87 is the smallest, what will be the range then?
Result:
<type in result here for desired result>
<type in result here for desired result>
<type in result here for desired result>
Need more info Sean
Hi Pat,
Thank you for your lisp, I'll study it to see if I can alter it for my task.
Regards
Sean
Hello Sean
Yes it will be very easy to patch the routine "TRI_POLY" to follow the Min-Max Values you need ...
(cons minvalue1 maxvalue1)
(cons minvalue2 maxvalue2)
etc
I have retested this old VLisp routine on my ACAD 2013 32 bits, it's OK !
Bye, Pat
Patrice BRAUD
Hi,
thank you for replying, sorry for being vague. I guess its not that important about the smallest area. If say I decide to divide it into 5 ranges, It would find the largest area and divide by 5 and round up to a whole number. In your example the range increment would be set to 105. (rounding up to nearest multiple of 5). Then 5 layers would be created (105,210,315,420,525) plines with areas >0 <105 into 105layer etc. and plines moved to those layers.
Pat (from other reply) kindly shared a lisp he had, do you think the code/part of is useful for me?
Regards
Sean
Hi Pat,
thank you, I'll try to alter/use your code. I'll let you know how I get on.
Regards
Sean
Go ahead and tryt Braudpat's code and tell me how it goes before i do any coding on my end 🙂
Cheers
BTW: why 105 and not 100 ?
Hello Sean
Please patch the TRI_POLY routine like that :
(cons 0 105)
(cons 105 210)
(cons 210 315)
(cons 315 420)
(cons 420 525)
And it will do the job !
Don't forget to answer S (for Surface) at the question Length or Surface (L/S) :?
Bye, Pat
Patrice BRAUD
Thanks Pat,
That does work but I need the ranges to be calculated by the routine by finding the largest area and dividing by number of ranges (user input) then round up the result to nearest multiple of x. (hopefully to a user input as well).
Question - how do I select pline with largest area?
Question - how do I round up to a multiple?
thanks for your time and input.
regards
Sean
<untested>
(defun c:ATL (/ round data ClosePolylines i e maxarea l) ; Area To Layer (vl-load-com) ;; pBe MAr2013 ;; ;; Kent Cooper for round fucntion ;; (defun round (num near) (* (fix (/ (+ num (/ near 2.0)) near)) near)) (if (And (Setq data nil l nil ClosedPolylines (ssget "_X" '((0 . "LWPOLYLINE,POLYLINE") (-4 . "<OR") (70 . 1) (70 . 5) (70 . 129) (70 . 133) (-4 . "OR>") ) ) ) (setq range (getint "\nEnter Range: ")) ) (progn (repeat (setq i (sslength ClosedPolylines)) (setq e (ssname ClosedPolylines (setq i (1- i)))) (setq Data (cons (list (vlax-curve-getArea e) e) Data)) ) (setq maxarea (apply 'max (mapcar 'car data))) (setq n (+ (round (/ maxarea range) range) range)) (repeat range (setq l (cons (* n range) l) range (1- range) ) ) (foreach itm data (setq lay (vl-some '(lambda (j k) (if (<= j (car itm) k) k ) ) (cons 0 l) l ) ) (setq e (entget (cadr itm))) (entmod (subst (cons 8 (itoa lay)) (assoc 8 e) e)) ) ) ) (princ) )
HTH
@sean.keohane wrote:Hi,
I need to segregate closed polylines in my drawing by area range. Ideally, I would input the number of ranges I need.
Then somehow find the smallest and largest pline area to determine the range values (rounding up to a sensble number)
Then with the ranges determined the polylines would be segregated and moved to new layers.
I've been trying to hobble together pieces but with no joy.
Can someone set me going with the correct approach, I'd appreciate it.
Regards
Sean
I was playing with this, and came up with the attached. It works a little differently from the descriptions in some of your later posts, but can be adjusted easily enough, which I will do later if you don't beat me to it.
The differences are that it divides the range in sizes of the existing closed Polylines, from the smallest to the largest, into the number of sub-ranges, rather than dividing the range from zero to the largest one. And it doesn't round the largest value up to base the range division on, but uses the size of the largest Polyline.
Anyway, see what you think, and I can make those changes later if you want.
Hello
BRAVO for pbejse and for Kent Cooper !
Bye, Pat
PS: Both routines tested on ACAD 2013 32 bits French
Patrice BRAUD
@pbejse wrote:....
.... (defun round (num near) (* (fix (/ (+ num (/ near 2.0)) near)) near)) ....
(setq n (+ (round (/ maxarea range) range) range)) ....
It would have been a little more efficient of me to do one thing the way you did, namely to use 'max [and under my original assumptions, 'min] in mine instead of sorting the whole list and getting the values from the first and last items. It would eliminate the need for my 'areasort' variable. Coming in adjusted routine....
Thanks for the credit on the rounding function. However, I see two problems with its use in the (setq n... rounding line quoted above:
1) That rounding function rounds up or down to the nearest multiple of its 'near' argument [here, the 'range' variable]. If it rounds up, it should be left at that value, without adding 'range' again.
2) If the area of the largest Polyline is exactly a multiple of the rounding value, it will likewise increase the subdividing value [here, the 'n' variable] to the next multiple above what it should be. That is, if the largest Polyline is 500 square units and the User asks for division into 5 categories, the 'n' result will be 105 rather than 100.
What's needed is a round-up-only approach that doesn't round up if the number is an exact multiple of the rounding value. [See my other routine, though that needs to be altered in other ways to do what they're looking for.]
@sean.keohane wrote:.... If say I decide to divide it into 5 ranges, It would find the largest area and divide by 5 and round up to a whole number. In your example the range increment would be set to 105. (rounding up to nearest multiple of 5). Then 5 layers would be created (105,210,315,420,525) plines with areas >0 <105 into 105layer etc. and plines moved to those layers.
....
Okay, the attached updated version of PolylineClassify.lsp seems to do those things [though I used a Layer naming convention that calls your example PLClass105], in limited testing. It could use some other stuff [error handling, undo begin/end, etc.], but give it a shot.
@Kent1Cooper wrote:
@pbejse wrote:
Thanks for the credit on the rounding function. However, I see two problems with its use in the (setq n... rounding line quoted above:
1) That rounding function rounds up or down to the nearest multiple of its 'near' argument [here, the 'range' variable]. If it rounds up, it should be left at that value, without adding 'range' again.
2) If the area of the largest Polyline is exactly a multiple of the rounding value, it will likewise increase the subdividing value [here, the 'n' variable] to the next multiple above what it should be. That is, if the largest Polyline is 500 square units and the User asks for division into 5 categories, the 'n' result will be 105 rather than 100.
What's needed is a round-up-only approach that doesn't round up if the number is an exact multiple of the rounding value. [See my other routine, though that needs to be altered in other ways to do what they're looking for.]
I noticed that too, Hence my question in post # 8 why he end up with 105 instead of 100. by removing the additional "range" value it will not conform with the OPs request.
It appears thats the OPs intention, not really sure.
I did had a look-see. interesting approach capturing polylines with area property. I may have to write an round-up-only routine or just use yours 🙂
Cheers
BTW: nice idea with the color assignment.
(defun c:ATL (/ round data ClosePolylines i e maxarea l) ; Area To Layer (vl-load-com) ;; pBe MAr2013 ;; ;; Kent Cooper for round fucntion ;; (defun round (num near) (* (fix (/ (+ num (/ near 2.0)) near)) near)) (if (And (Setq data nil l nil ClosedPolylines (ssget "_X" '((0 . "LWPOLYLINE,POLYLINE") (-4 . "<OR") (70 . 1) (70 . 5) (70 . 129) (70 . 133) (-4 . "OR>") ) ) ) (setq range (getint "\nEnter Range: ")) ) (progn (repeat (setq i (sslength ClosedPolylines)) (setq e (ssname ClosedPolylines (setq i (1- i)))) (setq Data (cons (list (vlax-curve-getArea e) e) Data)) ) (setq maxarea (apply 'max (mapcar 'car data))) (setq n (round (/ maxarea range) range) n (if (< (* n range) maxarea) (+ range n) n)) (repeat range (setq l (cons (* n range) l) range (1- range) ) (entmake (list (cons 0 "LAYER") (cons 100 "AcDbSymbolTableRecord") (cons 100 "AcDbLayerTableRecord") (cons 2 (itoa (car l))) (cons 62 (1+ range)) (cons 70 0))) ) (foreach itm data (setq lay (vl-some '(lambda (j k) (if (<= j (car itm) k) k ) ) (cons 0 l) l ) ) (setq e (entget (cadr itm))) (entmod (subst (cons 8 (itoa lay)) (assoc 8 e) e)) ) ) ) (princ) )
Following Kents advice, the additional "range" value will be added to n varaible only if the MAX area is LESS than the highest value of the calculated range. Also added color assignment.
HTH
@pbejse wrote:
@Kent1Cooper wrote:....1) That rounding function rounds up or down to the nearest multiple of its 'near' argument [here, the 'range' variable]. If it rounds up, it should be left at that value, without adding 'range' again.
....
I noticed that too, Hence my question in post # 8 why he end up with 105 instead of 100. by removing the additional "range" value it will not conform with the OPs request.
....
Here's my interpretation: Given your original for-example situation with the largest Polyline area being 502.36, and with the User asking for 5 categories/classifications, they want to divide 502.36 by 5, which gives 100.472. If the size of each category were 100, then the top category would go from 400 to 500, and the largest Polyline would not fall into any of the categories. That's why they want to round the size of each category up to the next multiple of whatever increment the User asks for -- in this case, if that's 5, up to 105. Then the top category is from 420 to 525, and the largest Polyline does fall within that range.
With my rounding function that rounds up or down to the nearest multiple, a divided value of 100.472 rounds down to 100, and it's necessary to add the 5 to that to get the category size to 105, so that the largest area will fall into the top size category.
But suppose the largest Polyline's area is 515 square units. Dividing that by 5 gives 103, which that rounding function will round up, to 105. Then if 5 is added, it becomes 110, and the top category is from 440 to 550. Yes, the largest Polyline will fall into that category, but the top category from 420 to 525, based on a category size of 105 without the extra 5 added, is enough to encompass that largest Polyline.
So if the rounding function rounds up, the extra 5 [or whatever the User's increment is] does not need to be added to ensure the largest Polyline is covered. It only needs to be added if the rounding function rounds down. But the same can be accomplished by having a rounding function that only rounds up.
But it should not round up if the starting value is an exact multiple. If the largest Polyline is 500 square units, with a divided value of 100, that should not be increased to 105, because the un-increased size of 100 will make a top category from 400 to 500, which will include the size of that largest Polyline.
Hello Kent
I appreciate your comments, so I have a new name for you : Rounder Manager !
Bye, Pat
Patrice BRAUD