End Points of 3dSolid Cylinder

End Points of 3dSolid Cylinder

Anonymous
Not applicable
2,274 Views
23 Replies
Message 1 of 24

End Points of 3dSolid Cylinder

Anonymous
Not applicable

I am trying to get the end points of a 3dSolid cylinder.

The cylinders can be in any direction 3 dimensionally.

I just don't have a clue how to transform the PrincipalDirections, etc. into a centroid point and then into vectors.

 

0 Likes
2,275 Views
23 Replies
Replies (23)
Message 2 of 24

Kent1Cooper
Consultant
Consultant

CENter Object Snap will get them for you.  If you want a routine to find them, entity data for 3D Solids is so inscrutable that I don't know how to get anything from that, but if you "dump" the cylinder's VLA Properties, you'll see several that look like point lists -- Centroid, MomentOfInertia, PrincipalMoments, RadiiOfGyration -- that you could experiment with.  The Centroid is clear enough, though the Property needs conversion:

 

(vlax-safearray->list (vlax-variant-value (vla-get-Centroid (vlax-ename->vla-object YourCylinderEntityName))))

 

Doing the same with the PrincipalDirections Property gives a list of 9 numbers, presumably making three vectors relative to the Centroid, but you'd need to play with them, probably adding them to the Centroid with (mapcar), and/or possibly using (trans) on them, to get the results you want.

Kent Cooper, AIA
0 Likes
Message 3 of 24

dbroad
Mentor
Mentor

One end of the cylinder axis is its position property.  The centroid property is the midpoint of its axis.  To get to the other end, find the dx,dy,dz between those 2 points and add twice the dx,dy, and dz to get to the other end.  If you really need a program, open the spoiler.

 

Spoiler
;returns a list of points describing a cylinder's axis
;;D. C. Broad - Demo
(defun c:test( / ss cyl pos mapd otherend)
(if (and
(setq ss (ssget ":S" '((0 . "3DSOLID"))))
(setq cyl (ssname ss 0))
(setq cyl (vlax-ename->vla-object cyl))
(= (vla-get-objectname cyl)"AcDb3dSolid")
(= (vla-get-solidtype cyl) "Cylinder")
)
(progn
(setq pos (vlax-get cyl 'position))
(setq mapd (mapcar '- (vlax-get cyl 'centroid) pos))
(setq otherend (mapcar '(lambda (a b) (+ a (* 2 b)))
pos mapd))
(list
pos
otherend)
)))

 

 

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 4 of 24

Anonymous
Not applicable

Kent - I tried each of the values, but I can't figure out what they mean.

Here are 10 values, ##=x is angle, posZ=up, negZ=down showing PrincipalDirections values.

   0 x, 1.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000
 45 x, 0.7071067812,-0.7071067812, 0.0000000000, 0.7071067812, 0.7071067812, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000
 90 x, 0.0000000000, 0.0000000000, 1.0000000000, 0.0000000000, 1.0000000000, 0.0000000000,-1.0000000000, 0.0000000000, 0.0000000000
135 x, 0.7071067812,-0.7071067812, 0.0000000000, 0.7071067812, 0.7071067812, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000
180 x, 1.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000
225 x, -0.5000000000, 0.5000000000,-0.7071067812, 0.7071067812, 0.7071067812, 0.0000000000, 0.5000000000,-0.5000000000,-0.7071067812
270 x, 0.0000000000, 0.0000000000, 1.0000000000, 0.0000000000, 1.0000000000, 0.0000000000,-1.0000000000, 0.0000000000, 0.0000000000
315 x, 0.7071067812,-0.7071067812, 0.0000000000, 0.6969234251, 0.6969234251,-0.1691019787, 0.1195731559, 0.1195731559, 0.9855985597
pos Z; 1.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000
neg Z; 1.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000

What I don't get is 0, 180, posZ & negZ are the same, 90 & 270 same, 45 & 135 same.

 

Dbroad - I already found the Centroid, but the Postion value is set to nil 'Automation Error. Description was not provided'. I don't know if it matters, but the cylinders are created by CADworx.

0 Likes
Message 5 of 24

hmsilva
Mentor
Mentor

@Anonymous wrote:

... 

Postion value is set to nil 'Automation Error. Description was not provided'. I don't know if it matters, but the cylinders are created by CADworx.


Hi mracad,

as a VlaObject, the Solidtype property is Cylinder, or Extrusion?

If Cylinder, could you please attach a sample with one or two cylinders.

 

Henrique

EESignature

0 Likes
Message 6 of 24

dbroad
Mentor
Mentor

If it doesn't work for you, it probably means you do not have a cylinder solid.  Instead you have cylindrical solids.  Nevertheless, it is possible to find what you seek through basic math based on the relationships between volume and mass moments if you are sure that the shapes are cylindrical.  See https://en.wikipedia.org/wiki/List_of_moments_of_inertia for the formula of the mass moments of a solid rod.  Solve for r and then based on the formula for the volume of a cylinder solve for h.

 

The principal axes will give you the orientation information.  I am sure the eager programers on this site will soon provide a solution for you.  Any formula based solution will give erroneous results if the input assumptions are false:   GIGO.

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 7 of 24

Anonymous
Not applicable

Here is a drawing with the 3dsolid cylinders. The cylinders are created by another program and don't have control over how they are created. I have to work with the existing entities.

Entities in the drawing -

Layer 1 = 1 cylinder going along z axis in positve Z direction

Layer 2 = 1 cylinder going along z axis in negative Z direction

Layer 3 = 8 cylinders rotated around z axis at 45 degree increments

Layer 4 = 8 cylnders at 45 degrees from x axis and rotated around z axis at 45 degree increments

Layer 5 = 8 cylnders at -45 degrees from x axis and rotated around z axis at 45 degree increments

 

Note - The cylinders represent a pipeline of any length and can be drawn in any direction 3-dimensionally. My goal is to find the end points of each cylinder and cut the cylinders into specific segments. Example - cut a pipe to 8' lengths with leftover at 1 end. This is why I need the endpoints of the center of the cylinders so I can calculate points along the axis of the cylinders. Note - the cylinders will always be straight segments. I don't have to worry about elbows or bends.

0 Likes
Message 8 of 24

dgorsman
Consultant
Consultant

Or, the maximum pipe length can be set in the CADWorx data catalog and have it cut into pieces from the start.  I wouldn't recommend trying to cut pre-2013 CADWorx pipe solids (but it can be done if you are *very* careful with the XDATA), and its impossible post-2013 with the custom objects.

----------------------------------
If you are going to fly by the seat of your pants, expect friction burns.
"I don't know" is the beginning of knowledge, not the end.


0 Likes
Message 9 of 24

Anonymous
Not applicable
I am working with post-2013 CADworx drawings that have the CADworx custom objects. I have exploded the custom objects and they have the same values as a 3Dsolid. I am not trying to modify the original objects. I am trying to read each object, then determine the endpoints so I can create new objects of the appropriate length.
0 Likes
Message 10 of 24

hmsilva
Mentor
Mentor

@Anonymous wrote:

...

 The cylinders represent a pipeline of any length and can be drawn in any direction 3-dimensionally. My goal is to find the end points of each cylinder and cut the cylinders into specific segments. Example - cut a pipe to 8' lengths with leftover at 1 end. This is why I need the endpoints of the center of the cylinders so I can calculate points along the axis of the cylinders. Note - the cylinders will always be straight segments. I don't have to worry about elbows or bends.


mracad,

I don't deal with CADWorx pipes, but if your goal is ' I need the endpoints of the center of the cylinders so I can calculate points along the axis of the cylinders.', we can use the XDATA...

This quick and dirty 'demo' will entmake a center line at selected solids

 

(defun c:demo (/ en i lst ss)
   (if (setq ss (ssget '((0 . "3DSOLID") (-3 ("CPD1")))))
      (repeat (setq i (sslength ss))
         (setq ent (entget (ssname ss (setq i (1- i))) '("CPD1")))
         (setq lst (vl-remove-if-not '(lambda (x) (= (car x) 1011)) (cdr (car (cdr (assoc -3 ent))))))
         (entmake (list '(0 . "LINE")
                        '(8 . "__Demo")
                        (cons 10 (cdr (nth 0 lst)))
                        (cons 11 (cdr (nth 1 lst)))
                  )
         )
      )
   )
   (princ)
)

 

Hope this helps,
Henrique

EESignature

0 Likes
Message 11 of 24

dbroad
Mentor
Mentor

This post should have been your first post.  It gives enough information to solve your specific needs without conjecture or misunderstanding.  It usually helps to attach a sample drawing.  In this case, all of your needed data is in the cadworkx xdata, which is attached to each pipe.  You can access the xdata yourself by using the expresstools xdlist command.  Cadworkx might also have some commands to assist you to do what you need without the kind of customization you are requesting.

 

In any case, Henrique seems to have given you a simple and straightforward strategy to do what you want.  

 

After you ask a question, please keep up with your thread without taking long pauses to reply.

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 12 of 24

Anonymous
Not applicable

Henrique...Thanks, quick and dirty will help for now.

 

Dbroad... Not a rant, just my observation...

 

This post should have been your first post.

I don't always now exactly how to express my thoughts well.

I thought - 'Endpoints of a 3dSolid Cylinder' was pretty self explanatory and I didn't know there were different types of solid objects.

 

It usually helps to attach a sample drawing.

I did finally attach a drawing.

 

In this case, all of your needed data is in the cadworkx xdata, which is attached to each pipe.

1. I didn't know there was Xdata attached to the objects.

2. Plus I don't want to rely on the Xdata, since it might change at anytime.

 

Cadworkx might also have some commands to assist you to do what you need without the kind of customization you are requesting.

I don't have CADWorx. I am using files from come from another company.

 

After you ask a question, please keep up with your thread without taking long pauses to reply.

I have to work for a living and sometimes I get busy and can't answer quickly.

 

Still, I am wondering if there is a way to use the following values to determine the endpoints -

Centroid

PrincipalDirections

PrincipalMoments

MomentOfInertia

ProductsOfInertia

RadiiOfGyration

 

I tried to follow these threads and quickly became lost -

http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/principal-direction-principal-moments...

http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/principaldirections-to-angle/m-p/2669...

 

0 Likes
Message 13 of 24

hmsilva
Mentor
Mentor

@Anonymous wrote:

Henrique...Thanks, quick and dirty will help for now.

...  

I don't want to rely on the Xdata, since it might change at anytime.

...

Still, I am wondering if there is a way to use the following values to determine the endpoints -

Centroid

PrincipalDirections

PrincipalMoments

MomentOfInertia

ProductsOfInertia

RadiiOfGyration

 ...


You're welcome, mracad

 

I also don't like to rely on Xdata on dwg's which were not produced by me.

 

This is not the answer you were waiting.

Determine the endpoints, using the Centroid, PrincipalDirections, ... ,RadiiOfGyration, I do not know either, but using Kailas Dhage's 'ACISdecode', probably It can be done.

Try the attached 'demo'.

 

Hope this helps,
Henrique 



Henrique

EESignature

0 Likes
Message 14 of 24

SEANT61
Advisor
Advisor

The array of data in the PrincipalDirections property are the X, Y, and Z components of the three vectors describing the principal directions. The XYZ of the First Vector are the 0,1,2 values in the array: Second Vector 3,4,5: Third 6,7,8.

 

To determine the vector aligned with the ‘length’ of a cylinder, use the vector corresponding to the smallest PrincipalMoments value. If the smallest principal moment value is in the second position, the cylinder is aligned with the Second Vector described above.

 

Of course, this breaks down if the ‘length’ of the cylinder is shorter than its diameter.


************************************************************
May your cursor always snap to the location intended.
0 Likes
Message 15 of 24

phanaem
Collaborator
Collaborator

@Anonymous wrote:

I am trying to get the end points of a 3dSolid cylinder.

The cylinders can be in any direction 3 dimensionally.

I just don't have a clue how to transform the PrincipalDirections, etc. into a centroid point and then into vectors.

 


A simple mod of this post will do the trick.

This lisp will draw lines from end to end

; Find cylinder ends
; Stefan M. - 01.09.2015
(defun c:pipes ( / ss i a)
  (if
    (setq ss (ssget '((0 . "3DSOLID"))))
    (repeat (setq i (sslength ss))
      (if
        (setq a (pipe_ends (ssname ss (setq i (1- i)))))
        (entmake (list '(0 . "LINE") (cons 10 (car a)) (cons 11 (cadr a))))
      )
    )
  )
  (princ)
  )

(defun pipe_ends (e / i v r l c d)
  (setq e (vlax-ename->vla-object e)
        v (vlax-get e 'Volume)
        i ((lambda (x)
             (if
               (equal (car x) (cadr x) (* 0.001 (car x)))
               (list (caddr x) (car x) 3)
               (if
                 (equal (car x) (caddr x) (* 0.001 (car x)))
                 (list (cadr x) (car x) 2)
                 (if
                   (equal (cadr x) (caddr x) (* 0.001 (cadr x)))
                   (list (car x) (cadr x) 1)
                 )
               )
             )
           )
           (vlax-get e 'PrincipalMoments)
          )
        )
  (if i
    (progn
      (setq r (sqrt (/ (* 2.0 (car i)) v))
            l (/ v (* pi r r)))
      (if
        (equal (/ (cadr i) (/ (* v (+ (* 3.0 r r) (* l l))) 12.0)) 1.0 1e-5)
        (progn
          (setq c (vlax-get e 'Centroid)
                d (vlax-get e 'PrincipalDirections)
                d (cond
                    ((= (caddr i) 1) (list (nth 0 d) (nth 1 d) (nth 2 d)))
                    ((= (caddr i) 2) (list (nth 3 d) (nth 4 d) (nth 5 d)))
                    ((= (caddr i) 3) (list (nth 6 d) (nth 7 d) (nth 8 d)))
                    )
                )
          (list
            (mapcar '(lambda (a b) (- a (* b l 0.5))) c d)
            (mapcar '(lambda (a b) (+ a (* b l 0.5))) c d)
          )
        )
      )
    )
  )
)

 

Message 16 of 24

hmsilva
Mentor
Mentor

@phanaem wrote:

A simple mod of this post will do the trick.

This lisp will draw lines from end to end


Nicely done.

 

Henrique

EESignature

0 Likes
Message 17 of 24

SEANT61
Advisor
Advisor

How about this 3dSolid Cylinder?


************************************************************
May your cursor always snap to the location intended.
0 Likes
Message 18 of 24

phanaem
Collaborator
Collaborator
OP says "pipe", so it is hard to believe this will be the case... My lisp will ignore elliptical cylinders or any other 3dsolid which is not a proper cylinder.
0 Likes
Message 19 of 24

marko_ribar
Advisor
Advisor

Hat off to Stefan, but it won't work with special cases cylinders... So Sean, have you tested it with h=r*(sqrt 3.0) ... This is the special case and not h=2r (diameter)... You can check it with my dwg and also with massprop command... Look into final principal moments about centroid (I,J,K)...

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes
Message 20 of 24

marko_ribar
Advisor
Advisor

Maybe it looks cumbersome and slow, but it works for all cylinders and only cylinder 3DSOLIDS... So I would give myself kudo for this one :

 

; Find cylinder ends
; Marko R. - 01.09.2015
(defun c:pipes ( / *adoc* *error* chkcyl qaf ss i cyl el s p1 p2 pll )

  (vl-load-com)
  (setq *adoc* (vla-get-activedocument (vlax-get-acad-object)))

  (defun *error* ( msg )
    (if qaf (setvar 'qaflags qaf))
    (vla-endundomark *adoc*)
    (if msg (prompt msg))
    (princ)
  )

  (defun chkcyl ( ent / el s chk )
    (vla-startundomark *adoc*)
    (setq el (entlast))
    (command "_.EXPLODE" ent)
    (while (< 0 (getvar 'cmdactive)) (command ""))
    (setq s (ssget "_P"))
    (while (not (eq el (entlast)))
      (command "_.EXPLODE" s)
      (while (< 0 (getvar 'cmdactive)) (command ""))
      (setq el (entlast))
      (setq s (ssget "_P"))
    )
    (if (and s (= (sslength s) 4) (eq (cdr (assoc 0 (entget (ssname s 0)))) "CIRCLE") (eq (cdr (assoc 0 (entget (ssname s 1)))) "CIRCLE") (eq (cdr (assoc 0 (entget (ssname s 2)))) "CIRCLE") (eq (cdr (assoc 0 (entget (ssname s 3)))) "CIRCLE"))
      (setq chk t)
      (setq chk nil)
    )
    (command "_.UNDO" "_B")
    chk
  )

  (vla-startundomark *adoc*)
  (setq qaf (getvar 'qaflags))
  (setvar 'qaflags 1)
  (prompt "\nSelect cylinder 3DSOLID entities...")
  (setq ss (ssget '((0 . "3DSOLID"))))
  (while (or (not ss) (and ss (not (apply 'and (mapcar 'chkcyl (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))))))
    (prompt "\nEmpty sel.set or one or more selected entities don't belong to cylinder 3dsolid entities... Please select cylinder 3DSOLID entities again...")
    (setq ss (ssget '((0 . "3DSOLID"))))
  )
  (repeat (setq i (sslength ss))
    (setq cyl (ssname ss (setq i (1- i))))
    (setq el (entlast))
    (command "_.EXPLODE" cyl)
    (while (< 0 (getvar 'cmdactive)) (command ""))
    (setq s (ssget "_P"))
    (while (not (eq el (entlast)))
      (command "_.EXPLODE" s)
      (while (< 0 (getvar 'cmdactive)) (command ""))
      (setq el (entlast))
      (setq s (ssget "_P"))
    )
    (if (and (eq (cdr (assoc 0 (entget (ssname s 0)))) "CIRCLE") (eq (cdr (assoc 0 (entget (ssname s 1)))) "CIRCLE"))
      (progn
        (setq p1 (trans (cdr (assoc 10 (entget (ssname s 0)))) (ssname s 0) 0) p2 (trans (cdr (assoc 10 (entget (ssname s 1)))) (ssname s 1) 0))
        (setq pll (cons (list p1 p2) pll))
      )
    )
    (command "_.UNDO" "_B")
  )
  (foreach pl pll
    (entmake (list '(0 . "LINE") (cons 10 (car pl)) (cons 11 (cadr pl))))
  )
  (*error* nil)
)

Regards, M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes