getting first intersecting 3dsolid and intersection point value along a line in autolisp.

getting first intersecting 3dsolid and intersection point value along a line in autolisp.

ShricharanaB
Advocate Advocate
1,604 Views
13 Replies
Message 1 of 14

getting first intersecting 3dsolid and intersection point value along a line in autolisp.

ShricharanaB
Advocate
Advocate

Hi, 

 

I want to check for the first 3d solid along a line. This line would be a starting point and the direction. The idea of this being, inserting a dynamic block at the starting point and extend it till the first intersection using dynamic stretch and parameter. 

This has to be independent of  current view. And the code will always run in WCS (even if the current view is different). 

I've shown here the line (just for representing, I'd just have a starting point and its angles)  and there are three random 3d solids on it's path. I want to get the first intersection point (on the green cube face). note that these are just to get across the idea and may not be actual situations.  the 3d solid may have any shape.

This 3d solid can be in any layer or have any color. 

ShricharanaB_1-1689324583687.png

ShricharanaB_2-1689324785857.png

ShricharanaB_0-1689684175128.png

 

 

How can I go about getting this point?

I'm using AutoCAD Mechanical 2020.

Thanks in advance for any help!

 

0 Likes
1,605 Views
13 Replies
Replies (13)
Message 2 of 14

hosneyalaa
Advisor
Advisor

Hi

Can you attached example drawing

0 Likes
Message 3 of 14

ShricharanaB
Advocate
Advocate

Hi @hosneyalaa,

 

Thank you for the reply. I've added the sample drawing. 

0 Likes
Message 4 of 14

hmsilva
Mentor
Mentor

@ShricharanaB 

programmatically, using AutoLISP / Visual LISP, I think it will not be possible to get the intersection point between the 'line' and a '3d solid may have any shape'.

 

We can use some workarounds to get the point.

 

There will be some user interference to select the 3DSolid?
If not, the dwg will have only three 3DSolis?

 

Henrique

EESignature

Message 5 of 14

CADaSchtroumpf
Advisor
Advisor

Maybe this could help you?

Take the "New" option and give the 3 points defining the plane, then select your line.

This line will be Trimed/Extended to this plane, you just have to interrogate the end of this line to get its coordinates.

(defun c:int_3d ( / js nw_ucs dxf_ent dxf_10 dxf_11 p10_2d p11_2d p_int)
  (initget "New Current")
  (setq nw_ucs (getkword "\nUse UCS [New/Current] <Current>: "))
  (if (eq nw_ucs "New")
    (command "_.ucs" "_3point" pause pause pause)
  )
  (princ "\nSelect the line to Extend/Trim to a section plane: ")
  (while (null (setq js (ssget "_:S"  '((0 . "LINE")))))
    (princ "\nEmpty selection or not a line!")
  )
  (while js
    (setq
      dxf_ent (entget (ssname js 0))
      dxf_10 (trans (cdr (assoc 10 dxf_ent)) 0 1)
      dxf_11 (trans (cdr (assoc 11 dxf_ent)) 0 1)
      p10_2d (list (car dxf_10) (cadr dxf_10) 0.0)
      p11_2d (list (car dxf_11) (cadr dxf_11) 0.0)
      p_int (inters p10_2d p11_2d dxf_10 dxf_11 nil)
    )
    (cond
      (p_int
        (if (> (distance p_int p11_2d) (distance p_int p10_2d))
          (entmod (subst (cons 10 (trans p_int 1 0)) (assoc 10 dxf_ent) dxf_ent))
          (entmod (subst (cons 11 (trans p_int 1 0)) (assoc 11 dxf_ent) dxf_ent))
        )
      )
      (T
        (princ "\nLine parallel to the cutting plane!")
      )
    )
    (princ "\nSelect the line to Extend/Trim: <Enter for exit>: ")
    (setq js (ssget "_:S"  '((0 . "LINE"))))
  )
  (if (eq nw_ucs "New")
    (command "_.ucs" "_previous")
  )
  (prin1)
)
Message 6 of 14

ShricharanaB
Advocate
Advocate

@hmsilva 

The drawing may have all possible object types blocks, 3dsolids, meshes etc.

Currently idea is not to select 3d solids. But if a selection of made to select multiple 3d solids in one selection would it help? 

@CADaSchtroumpf 

Thank you for taking your time for writing this code!.
How ever, the idea is to check for these intersections at multiple locations (may be in hundreds ) ( line starting at different locations, going parallelly , not from a single point)  as required and get the point so the distance between the line start point and the first intersection point can be found so that I can calculate the distance between the two. 


I think the snapshots I added earlier may not be enough, attaching a snap which can make it clearer, I think.

ShricharanaB_1-1689682120823.png

 

Each point from which this should be done is dependent on something else. If I can figure out from one point I can do the same for the rest.

 

0 Likes
Message 7 of 14

hosneyalaa
Advisor
Advisor

hi

@ShricharanaB  try

from  link

http://www.theswamp.org/index.php?topic=40494.msg457913#msg457913

 

 

;;Break 3d lines by a 3d Plane
;;;Author: Chen Qing Jun, qjchen
;;;Programed by: South China University of Technology
;;;date: 2011.12.19
;;;Note: the intersection function of Line and Plane, has the parameter of nil and T
;;;      For T, the line segment should pass through the plane
;;;      but it is not necessary for the nil parameter.
;;;      The plane defined by 3p is infinite.
;;; 
;;; http://www.theswamp.org/index.php?topic=40494.msg457913#msg457913
;;;
;;;_Some vector function, some get from gile's great function________________
;;;
(defun q:geo:is-3p-plane(p1 p2 p3)
 (> (q:vec:Len (q:vec:Norm (q:vec:cross* (q:vec:- p2 p1) (q:vec:- p3 p1)))) 1e-6)
)
(defun q:geo:is-samepoint(p1 p2) (< (distance p1 p2) 1e-5) )
(defun q:vec:+(v1 v2) (mapcar '+ v1 v2) )
(defun q:vec:-(v1 v2) (mapcar '- v1 v2) )
(defun q:vec:*c(v a) (mapcar '(lambda(x) (* x a)) v) )
(defun q:vec:dot*(v1 v2) (apply '+ (mapcar '* v1 v2)) )
(defun q:vec:cross*(v1 v2)
  (list (q:det:2 (cadr v1) (caddr v1) (cadr v2) (caddr v2))
        (q:det:2 (caddr v1) (car v1) (caddr v2) (car v2))
        (q:det:2 (car v1) (cadr v1) (car v2) (cadr v2))) 
)
;;;;cal determinant
;;;;|a1 a2|
;;;;|b1 b2|
(defun q:det:2(a1 a2 b1 b2)  (- (* a1 b2) (* a2 b1)))
;;;;Normalize a vector
(defun q:vec:Norm(v / l)
  (if (not (zerop (setq l (distance '(0 0 0) v))))
  (mapcar '(lambda(x) (/ x l)) v))
)
;;;;Vector Length
(defun q:vec:Len(v / l)  (distance '(0 0 0) v))
;;;;a normal to a plane, 
(defun q:geo:normal.to.3p(p1 p2 p3)
  (if (q:geo:is-3p-plane p1 p2 p3)(q:vec:cross* (q:vec:- p2 p1) (q:vec:- p3 p1)))
)
;;p1 p2 are two points,V is the normal of the plane, VP is one point on the plane
;;ref:   http://en.wikipedia.org/wiki/Line-plane_intersection
;;       http://softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm
(defun q:geo:line-intersect-plane-1(P1 P2 V VP F / d l n)
 (setq n (q:vec:Norm V) l (q:vec:Norm (q:vec:- P2 P1)))
 (if (not (zerop (q:vec:dot* l n)))
   (progn
     (setq d (/ (q:vec:dot* (q:vec:- VP P1) n) (q:vec:dot* l n)))
     (setq res (q:vec:+ P1 (q:vec:*c l d)))
     (setq temp (q:vec:Len (q:vec:- P2 P1)))
     (if (and F (or (< d 0) (> d (q:vec:Len (q:vec:- P2 P1))))) (setq res nil)) 
   )
 )
 res
)
;;;;;;______end of Vector function__________________________________;;;
(defun q:entmake:point(pt layer)
  (entmake (list (cons 0 "POINT")(cons 8 layer)(cons 10 pt)))
)
(defun q:mulentmod (ent numlst contentlst / i x)
  (setq i 0)
  (foreach x numlst
    (if (/= (assoc x ent) nil)
      (setq ent (subst (cons x (nth i contentlst)) (assoc x ent) ent ) )
      (setq ent (append ent (list (cons x (nth i contentlst))) ) )
    )
    (setq i (1+ i))
  )
  (entmod ent)  ;(entupd ent)
)
;;;;;stdlib from Reini Urban
(defun std-sslist (ss / n lst)
  (if (eq 'pickset (type ss))
    (repeat (setq n (fix (sslength ss))) ; fixed
      (setq lst (cons (ssname ss (setq n (1- n))) lst))
    )
  )
)
;;;???______by qjchen____________________________;;;
(defun c:PBL()
  (setq p1 (getpoint "\nThe first point:") p2 (getpoint "\nThe second point:") p3 (getpoint "\nThe third point:"))
  (if (q:geo:is-3p-plane p1 p2 p3)
    (progn 
      (setq c (std-sslist(ssget '((0 . "LINE")))))
      (setq pn (q:geo:normal.to.3p p1 p2 p3))
      (foreach x c
       (setq pa (cdr (assoc 10 (entget x))) pb (cdr (assoc 11 (entget x))))
       (setq int (q:geo:line-intersect-plane-1 pa pb pn p1 T))
       
       (if (and int (not (q:geo:is-samepoint int pa))(not (q:geo:is-samepoint int pb)))
	  (progn
            (q:mulentmod (entget (entmakex (entget x))) (list 62 11) (list 1 int))
	    ;(q:mulentmod (entget (entmakex (entget x))) (list 62 10) (list 2 int))
	    (entdel x)
	    ;(q:entmake:point int "0")
	 )
	 )
      )
    )
    (princ "\n These three points can not form a plane.")
  )
)

(princ)
(princ "\n Break 3d lines by a 3d Plane,by qjchen,the command is :test")
(princ)

 

 

990.gif

 

Message 8 of 14

marko_ribar
Advisor
Advisor

You coded too much...

I am afraid that OP don't know which 3DSOLID is first on detection... So IMHO, for each line user must obtain all intersecting points AFAIK only with IMPRINT command and for each line, OP should check for closest point to starting point... This is how I see this task... I may be wrong, but picking 3 points for plane definition is total miss of the task... So long from me... Bye...

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 9 of 14

Kent1Cooper
Consultant
Consultant

The PBL command approach is all well and good if the first thing encountered has a flat face like that.  But "any shape" could be [for example] a sphere or cylinder or cone, or something very convoluted, for which that would not be a solution.

Kent Cooper, AIA
Message 10 of 14

hmsilva
Mentor
Mentor

@ShricharanaB wrote:

@hmsilva 

The drawing may have all possible object types blocks, 3dsolids, meshes etc.

Currently idea is not to select 3d solids. But if a selection of made to select multiple 3d solids in one selection would it help? 

@CADaSchtroumpf 

Thank you for taking your time for writing this code!.
How ever, the idea is to check for these intersections at multiple locations (may be in hundreds ) ( line starting at different locations, going parallelly , not from a single point)  as required and get the point so the distance between the line start point and the first intersection point can be found so that I can calculate the distance between the two. 


I think the snapshots I added earlier may not be enough, attaching a snap which can make it clearer, I think.

ShricharanaB_1-1689682120823.png

 

Each point from which this should be done is dependent on something else. If I can figure out from one point I can do the same for the rest.

 


@ShricharanaB I was thinking to use rays using the starting point and the direction
test each ray with all 3dsolids using the command 'PROJECTGEOMETRY'
test if new entities were added
test if the new entities are intersecting ray object using the IntersectWith method and store the resulting points in a list
find the nearest point to the start point
delete ray and the new entities

 

it will be very slow the idea is to check for these intersections at multiple locations (may be in hundreds) 

 

Hope this helps,
Henrique

EESignature

Message 11 of 14

hosneyalaa
Advisor
Advisor

@Kent1Cooper 

Yes, as you explained So I asked from him to be attached Example drawing Let's see what he has shapes

Message 12 of 14

Kent1Cooper
Consultant
Consultant

I expected that (ssget) using Fence selection with the Line endpoints would be the answer, because from it you can get all the things that the Fence intersects, in order, and the locations at which it intersects them.  But it doesn't work -- there must be something peculiar about how it calculates where a Fence line "intersects" a 3D Solid.  I set up a very clean situation in which all the findings should be in whole-number values, but they're not.  It did, at least, in very limited trial, identify the first object that the Fence encountered out of several, but did not report the right location for where it hit.

Kent Cooper, AIA
Message 13 of 14

leeminardi
Mentor
Mentor

Assuming that you have a collection of 3ds solids that "may have any shape" and you wish to find the first intersection of a line with that set of solids here is an approach that may be programmable in VLISP.

  1. Union the set of solids together.
  2. sweep a small triangle using the line as a path.
  3. Perform a Boolean intersect with the results of #1 and #2.
  4. align3d the results (solid and line) such that the intersection line is parallel to the x axis of the WCS.
  5. Get the minimum x coordinated of the bounding box.
  6. place a point on the line with the x coordinate of #5.
  7. Reverse the alignment that was done in step #4.
  8. The point is now at the first intersection! 

Note, the task that you are asking is essentially done via z-buffering during the rendering process. Perhaps a rendering engine that enables you to access the z-buffered result could be used.

lee.minardi
Message 14 of 14

Sea-Haven
Mentor
Mentor

Just a real guess, allowing for a tolerance of like 0.00001 if we make the line a solid then can subtract the shape from it. So get end points of solid line maybe a radius of 0.00000001 for a circle extruded along path. get answers then undo so original shape is returned.

 

SeaHaven_0-1689730618081.png