Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Divide multiple lines

35 REPLIES 35
Reply
Message 1 of 36
Haggoo
2175 Views, 35 Replies

Divide multiple lines

Hi,

 

I need to divide thousands of lines into half, but AutoCAD divide command can only allow you to select one line at a time.Is there any way we can divide multiple lines  at once.

 

Thanks

35 REPLIES 35
Message 21 of 36
BlackBox_
in reply to: Patchy


@Patchy wrote:

I used the one Kent wrote.


In the future, perhaps it would be prudent for you not fail to specify that... The OP thanked Dbroad for his routine, asked for the revisiong to include Polylines, and you offer advise for someone else's routine.

 

I'm sure you can see how you comment may have confuesed someone less adept at coding LISP.

 

In any event, thanks for clarifying here.

 

Cheers



"How we think determines what we do, and what we do determines what we get."

Message 22 of 36
BlackBox_
in reply to: dbroad

Hey Dbroad,

 

If I might offer another suggestion for your consideration... Following your iteration of the ActiveSelectionSet Object, your should use vla-Delete, as there's a finite number of allowed SelectionSets, and each iteration of the routine otherwise adds another one to the stack:

 

  (vlax-for x (setq ss (vla-get-activeselectionset acDoc))
    ;;<-- do work
  )
  (vla-delete ss)

 

 Cheers



"How we think determines what we do, and what we do determines what we get."

Message 23 of 36
dbroad
in reply to: Haggoo

Here is one that handles arcs, lines, and lwpolylines.

(vl-load-com)
(defun c:mdivide  (/ doc spc blk)
  ;;D. C. Broad, Jr.  4/2013
  (setq	doc (vla-get-activedocument (vlax-get-acad-object))
	spc (vla-get-activespace doc)
	blk (if	(= spc 1)
	      (vla-get-modelspace doc)
	      (vla-get-paperspace doc)
	      ))
  (if (ssget '((0 . "LINE,LWPOLYLINE,ARC")))
    (progn
      (vla-startundomark doc)
      (vlax-for	n  (vla-get-activeselectionset doc)
	(setq name (vla-get-objectname n))
	(cond
	  ((member name '("AcDbLine" "AcDbArc"))
	   (vlax-invoke
	     blk
	     'addpoint
	     (vlax-curve-getpointatparam  n
	       (/ (+ (vlax-curve-getstartparam n)
		     (vlax-curve-getendparam n))
		  2.0)
	       )))
	  ((= name "AcDbPolyline")
	   (setq end (vlax-curve-getendparam n))
	   (setq d 0.5)
	   (while (< d end)
	     (vlax-invoke
	       blk
	       'addpoint
	       (vlax-curve-getpointatparam n d))
	     (setq d (1+ d))
	     ))
	  )
	))
    (vla-endundomark doc)
    )
  (princ)
  )

 

Architect, Registered NC, VA, SC, & GA.
Message 24 of 36
BlackBox_
in reply to: BlackBox_

As a demonstration, here's a speed test using a selection set of a single Line object, and slight modification to both routines to accept said selection set as an argument.

 

Disclaimer: If I've incorrectly modified another's code, which may be responsible for a discrepancy in performance, please correct me where I am wrong.

 

Speed test:

(defun _DL2 ( ss / cmde ss1)
  (setq cmde (getvar 'cmdecho))
  (setvar 'cmdecho 0)
  (command "_.undo" "_begin")
  (setq ss1 ss)
  (repeat (sslength ss1)
    (command "_.divide" (ssname ss1 0) 2)
    (ssdel (ssname ss1 0) ss1)
  ) 
  (command "_.undo" "_end")
  (setvar 'cmdecho cmde)
)

(defun _PointAtMid (ss / *error* ss acDoc oSpace tab)

  (defun *error* (msg)
    (if acDoc
      (vla-endundomark acDoc)
    )
    (cond ((not msg))                                                   ; Normal exit
          ((member msg '("Function cancelled" "quit / exit abort")))    ; <esc> or (quit)
          ((princ (strcat "\n** Error: " msg " ** ")))                  ; Fatal error, display it
    )
    (princ)
  )

  (vla-startundomark
    (setq acDoc (vla-get-activedocument (vlax-get-acad-object)))
  )
  (setq oSpace
         (apply
           (if (setq tileMode (= 1 (getvar 'tilemode)))
             'vla-get-modelspace
             'vla-get-paperspace
           )
           (list acDoc)
         )
  )
  (vlax-for x (setq ss (vla-get-activeselectionset acDoc))
    (vla-addpoint
      oSpace
      (vlax-3d-point
        (vlax-curve-getpointatdist x (* 0.5 (vla-get-length x)))
      )
    )
  )
  (vla-delete ss)
  (*error* nil)
)

(bench '(_DL2 _PointAtMid) '(ss) 1000)

 

... Results from console:

_DL2
Elapsed: 109746
Average: 109.7460

_POINTATMID
Elapsed: 670
Average: 0.6700

 

Disregarding the Polyline support, etc... On pure performance alone, this is a no brainer... More specifically, _PointAtMid could have run +/-160 times in the same time required for _DL2 to complete only a single (1) iteration, over a single (1) line:

(bench '(_DL2) '(ss) 1)

(bench '(_PointAtMid) '(ss) 200)

 ... Yields:

_DL2
Elapsed: 125
Average: 125.0000

_POINTATMID
Elapsed: 125
Average: 0.6250

 

 

Further, while I have not made the time to check out the per-segment routine receiving such a hard-sell here (perhaps I should?), one can easily refactor my offering to allow for both total length, and per-segment point orientation as desired. Lemon squeezy.

 

Cheers



"How we think determines what we do, and what we do determines what we get."

Message 25 of 36
_Tharwat
in reply to: dbroad

Hope you don't mind guys .

 

(defun c:Test (/ ss i sn)
  (or doc (setq doc (vla-get-activedocument (vlax-get-acad-object))))
  (if (setq ss (ssget '((0 . "ARC,LINE,LWPOLYLINE"))))
    (progn
      (vla-StartUndoMark doc)
      (repeat (setq i (sslength ss))
        (setq sn (ssname ss (setq i (1- i))))
        (entmakex (list '(0 . "POINT") (cons 10 (vlax-curve-getpointatdist sn
                                (/ (vlax-curve-getdistatparam sn (vlax-curve-getendparam sn)) 2.)
                              ) ) ) )
      )
      (vla-endUndomark doc)
    )
  )
  (princ)
)
(vl-load-com)

 

Message 26 of 36
BlackBox_
in reply to: dbroad

Dbroad, there's no need to distinguish between ObjectNames... Consider this slight modification to my original code:

(vl-load-com)

(defun c:PointAtMid (/ *error* ss acDoc oSpace)

  (defun *error* (msg)
    (if acDoc
      (vla-endundomark acDoc)
    )
    (cond ((not msg))                                                   ; Normal exit
          ((member msg '("Function cancelled" "quit / exit abort")))    ; <esc> or (quit)
          ((princ (strcat "\n** Error: " msg " ** ")))                  ; Fatal error, display it
    )
    (princ)
  )

  (if (setq ss (ssget '((0 . "ARC,LINE,*POLYLINE"))))
    (progn
      (vla-startundomark
        (setq acDoc (vla-get-activedocument (vlax-get-acad-object)))
      )
      (setq oSpace (apply (if (getvar 'tilemode)
                            'vla-get-modelspace
                            'vla-get-paperspace
                          )
                          (list acDoc)
                   )
      )
      (vlax-for x (setq ss (vla-get-activeselectionset acDoc))
        (vla-addpoint
          oSpace
          (vlax-3d-point
            (vlax-curve-getpointatparam
              x
              (* 0.5
                 (+ (vlax-curve-getstartparam x)
                    (vlax-curve-getendparam x)
                 )
              )
            )
          )
        )
      )
      (vla-delete ss)
    )
    (prompt "\n** Nothing selected ** ")
  )
  (*error* nil)
)

 



"How we think determines what we do, and what we do determines what we get."

Message 27 of 36
BlackBox_
in reply to: _Tharwat


@_Tharwat wrote:

Hope you don't mind guys .

 

(defun c:Test (/ ss i sn)
  (or doc (setq doc (vla-get-activedocument (vlax-get-acad-object))))
  (if (setq ss (ssget '((0 . "ARC,LINE,LWPOLYLINE"))))
    (progn
      (vla-StartUndoMark doc)
      (repeat (setq i (sslength ss))
        (setq sn (ssname ss (setq i (1- i))))
        (entmakex (list '(0 . "POINT") (cons 10 (vlax-curve-getpointatdist sn
                                (/ (vlax-curve-getdistatparam sn (vlax-curve-getendparam sn)) 2.)
                              ) ) ) )
      )
      (vla-endUndomark doc)
    )
  )
  (princ)
)
(vl-load-com)

 


Not at all, Tharwat... That's an excellent adaptation. 

 

Cheers



"How we think determines what we do, and what we do determines what we get."

Message 28 of 36
_Tharwat
in reply to: BlackBox_


@BlackBoxCAD wrote:

@_Tharwat wrote:

Hope you don't mind guys .

 



Not at all, Tharwat... That's an excellent adaptation. 

 

Cheers


Thank you mate , it's very kind of you . Smiley Happy

Message 29 of 36
Kent1Cooper
in reply to: BlackBox_


@BlackBoxCAD wrote:

As a demonstration, here's a speed test using a selection set of a single Line object, and slight modification to both routines to accept said selection set as an argument.

....

... Results from console:

_DL2
Elapsed: 109746
Average: 109.7460

_POINTATMID
Elapsed: 670
Average: 0.6700

 

... _PointAtMid could have run +/-160 times in the same time required for _DL2 to complete only a single (1) iteration, over a single (1) line:

(bench '(_DL2) '(ss) 1)

(bench '(_PointAtMid) '(ss) 200)

 ... Yields:

_DL2
Elapsed: 125
Average: 125.0000

_POINTATMID
Elapsed: 125
Average: 0.6250

....


Yes, certainly the approach used in DL2 takes longer as acknowledged, but in at least one way, that benchmark test is not a valid indicator of the time it takes either routine to mark 1000 Lines, and therefore maybe not a very meaningful comparison.  It runs the entire routines 1000 times, including, in the case of _DL2, the turning off and back on of command-line echoing, and in the case of _PointAtMid, the defining and running of the error handler, and in both cases, the Undo begin/end switching, all of those occurring 999 times more than they would if either routine were used on 1000 Lines in a single selection.  If the 'Elapsed' values are in milliseconds, your benchmark on _DL2 took roughly 25 times as long as it took my computer to mark 1000 Lines in a single selection ["measured" by counting off the roughly 4 seconds it took in my head, not by a benchmark test].  That would suggest to me that the 999 extra CMDECHO/Undo togglings in the benchmark test take up the great bulk of the excess time, which in turn suggests that with those occurring only once, as would be the case in actual operation, the time difference between the two routines would be considerably less.  But _PointAtMid should also take less time [whether proportionally less, I couldn't say], and _DL2 will definitely still take longer.  I'd be interested in the results of a similar test, using a selection set of 1000 Lines and running once.

 

Another consideration is whether the amount of time saved amounts to anything worth worrying about, which again depends largely on how many Lines you're likely to be marking.  For the single Line, run once, again if the 'Elapsed' value is in milliseconds, _DL2 takes a very cumbersome 1/8 of a second.  Even if PointAtMid takes only about 1/1300 of a second to do the same, such a time savings would be functionally meaningless to a User selecting a single Line.

Kent Cooper, AIA
Message 30 of 36
BlackBox_
in reply to: Kent1Cooper


@Kent1Cooper wrote:

Yes, certainly the approach used in DL2 takes longer as acknowledged, but in at least one way, that benchmark test is not a valid indicator of the time it takes either routine to mark 1000 Lines, and therefore maybe not a very meaningful comparison.  It runs the entire routines 1000 times, including, in the case of _DL2, the turning off and back on of command-line echoing, and in the case of _PointAtMid, the defining and running of the error handler, and in both cases, the Undo begin/end switching, all of those occurring 999 times more than they would if either routine were used on 1000 Lines in a single selection.  If the 'Elapsed' values are in milliseconds, your benchmark on _DL2 took roughly 25 times as long as it took my computer to mark 1000 Lines in a single selection ["measured" by counting off the roughly 4 seconds it took in my head, not by a benchmark test].  That would suggest to me that the 999 extra CMDECHO/Undo togglings in the benchmark test take up the great bulk of the excess time, which in turn suggests that with those occurring only once, as would be the case in actual operation, the time difference between the two routines would be considerably less.  But _PointAtMid should also take less time [whether proportionally less, I couldn't say], and _DL2 will definitely still take longer.  I'd be interested in the results of a similar test, using a selection set of 1000 Lines and running once.

 

Another consideration is whether the amount of time saved amounts to anything worth worrying about, which again depends largely on how many Lines you're likely to be marking.  For the single Line, run once, again if the 'Elapsed' value is in milliseconds, _DL2 takes a very cumbersome 1/8 of a second.  Even if PointAtMid takes only about 1/1300 of a second to do the same, such a time savings would be functionally meaningless to a User selecting a single Line.


That's a valid argument... Repeat is quite efficient, as compared to obtaining the VL Selection Set Object, the erro handler is of little consequence, and I cannot speak for the Command invocation. I would think that the former alone you'd see similar speeds over large data sets, but that's not how most users work (with exception to the occasional batch process).

 

As is the case with most speed tests... Hardware configuration, and effeciency of user, and/or repeated calls will dictate, and usually lend to the speed difference being negligible in the real-world. I do it mostly to challenge myself.

 

In any event, this has been a fun little excercise... Makes me wonder what the gain in efficiency will be when I port this sample to .NET API. *geek*



"How we think determines what we do, and what we do determines what we get."

Message 31 of 36
dbroad
in reply to: BlackBox_

"Dbroad, there's no need to distinguish between ObjectNames..."

 

It depends on what you want to do. I do know what I'm doing. Consider the images below. 

 

 

compare.png

 

But technically there might be a problem with my last loop on polylines.  I do believe it works though.

Architect, Registered NC, VA, SC, & GA.
Message 32 of 36
dbroad
in reply to: BlackBox_

Deleting selection sets IMO is of virtually no value.  AutoCAD cleans itself up.

Architect, Registered NC, VA, SC, & GA.
Message 33 of 36
BlackBox_
in reply to: dbroad


@dbroad3 wrote:

Deleting selection sets IMO is of virtually no value.  AutoCAD cleans itself up.


For the purposes of truth, and clarity, I must correct my earlier statement, as it is not fully acurate... To paraphrase R. Robert Bell:

 

 

 

AutoCAD only supports 128 selections sets, and does clean itself up for those selection sets that are bound to a local variable, when said variable goes out of scope.

 

AutoCAD does not clean itself up when ActiveX selection sets are created via the Add method:

(setq foo (vla-add (vla-get-selectionsets acDoc) "foo"))

 

... Even when this Object is bound to a local variable, it is not automatically closed when the variable goes out of scope. This is the reason for the Delete method on created ActiveX selection sets.

 

This however, is not as issue when using the ActiveSelectionSet Property Object, as that is not an Object created by you, and is managed by AutoCAD.

 

 

 

My usage of the Delete Method stems back to when I first learned of iterating Selection Sets from Robert (I didn't know what a Defun was until litteraly a few years ago), and in that discussion, it was identified as a 'no harm, no foul' addition to one's code, thus I chose to include it regardless, but technically the Delete method is not necessary in my offering.

 

Sorry for any confusion my earlier statement may have caused.



"How we think determines what we do, and what we do determines what we get."

Message 34 of 36
BlackBox_
in reply to: dbroad


@dbroad3 wrote:

 

It depends on what you want to do. I do know what I'm doing.  


Agreed... I never said you don't know what you're doing... I chose to offer code that does exactly what the OP requested, in lieu of what has been twice offered by others with no response from OP... Take from it what you like.

 

Cheers



"How we think determines what we do, and what we do determines what we get."

Message 35 of 36
dbroad
in reply to: BlackBox_

No problem.  I typically try to leave the cleanup to the processor as much as possible.  I did forget to scope a few variables that were intended to be local in the last version I posted.  There was a time when storing ActiveX objects did lock up lots of storage.  I believe they have fixed some of the memory problems that were prone to happen in earlier versions.

Architect, Registered NC, VA, SC, & GA.
Message 36 of 36
BlackBox_
in reply to: dbroad


@dbroad3 wrote:

No problem.  I typically try to leave the cleanup to the processor as much as possible.  I did forget to scope a few variables that were intended to be local in the last version I posted.  There was a time when storing ActiveX objects did lock up lots of storage.  I believe they have fixed some of the memory problems that were prone to happen in earlier versions.


It is always appreciated to not only see others' code, but to have an opportunity to have an honest discussion about the logic and tradeoffs of the 'how and why' behind a given implementation... Knowledge gained offers greater possability of earning wisdom.

 

Cheers, Dbroad 



"How we think determines what we do, and what we do determines what we get."

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost