Author Topic: {=-Challenge-=} - closestpointto on reference surface from 3D point in space  (Read 10671 times)

0 Members and 1 Guest are viewing this topic.

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
Similar to what function (vlax-curve-getclosestpointto curve wcspt) do with reference curve, the task is now to find point on surface that is closest to reference point in 3D space...

Here on picture I marked point from as center of red sphere and in attachment there is also DWG with the same describing the task - problem...

IMHO I don't think this could be solved by using ALISP, but rather some other approach...
As a result I am expecting operational function that can operate correctly for all 3D entities such as 3DSOLIDs, SURFACEs, REGIONs, BODY entities, NURBS SURFACEs and all 3D Modeler entities...

Thanks for reading, may the competition begin...
M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
Just as addition...

Hint : You can start with very small sphere with point as center and make it grow until it touches SURFACE... That point of touch would be solution...
But then again this is slow process...
There is a case where there could be multiple solutions (for ex. reference point is in center of reference SURFACE converted from SPHERE)...
In this case I suppose that solution would be intersection of X axis through center and SURFACE-SPHERE...
Similary if there are more than 1 soultion - the first one closest to X axis vector from reference point would be correct one... All in all - instead of (vlax-curve-getclosestpointto), you need to code for (vlax-surface-getclosestpointto) - results should be very similar in the way it is behaving with multiple solutions - single point (not list of points)...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
This is preliminary result that I got with applying this function with sel. set of red curves describing surface...

Code: [Select]
(defun vlax-surface-getclosestpointto ( ss pt / i c pl )

  (vl-load-com)

  (repeat (setq i (sslength ss))
    (setq c (ssname ss (setq i (1- i))))
    (if (/= (cdr (assoc 0 (entget c))) "VERTEX")
      (setq pl (cons (vlax-curve-getclosestpointto c pt) pl))
    )
  )
  (car (vl-sort pl '(lambda ( a b ) (< (distance a pt) (distance b pt)))))
)

(setq p (vlax-surface-getclosestpointto ss pt))

Look in attachment - there is DWG for you to compare your result...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

BIGAL

  • Swamp Rat
  • Posts: 1411
  • 40 + years of using Autocad
A man who never made a mistake never made anything

BIGAL

  • Swamp Rat
  • Posts: 1411
  • 40 + years of using Autocad
The answer may be more in using a TIN Triangular irregular network. If the point can have a 90 projection and land on the surface is 1st step 2nd would be to compare distances. There is math theory for vector to 3 points. Just don't ask me how to do in lisp.

Using 3 points you can set a UCS plane going through 3 points then the point would have a z the distance off.
« Last Edit: October 29, 2019, 03:53:27 AM by BIGAL »
A man who never made a mistake never made anything

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
The answer may be more in using a TIN Triangular irregular network. If the point can have a 90 projection and land on the surface is 1st step 2nd would be to compare distances. There is math theory for vector to 3 points. Just don't ask me how to do in lisp.

Using 3 points you can set a UCS plane going through 3 points then the point would have a z the distance off.

I don't think you can achieve desirable results with TIN - in terms of timing of computation... Beside that you can never interpolate surface with desirable amount of points and further more after TIN, curving of surface would be neglected - you can always get Z of 3 points and reference point in space, but to flat plane - not apex point of surface curving shape... My method of finding preliminary point is my best approach, just don't know how to proceed after that - result is never exact like it is with (vlax-curve-xxx) functions...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
In BricsCAD the ZPERpendicular snap actually behaves as a 'closest point to surface' snap (at least in V18).
The distance between the point object in the DWG and the point found by BC is 0.10 units.

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1453
  • Marco
In BricsCAD the ZPERpendicular snap actually behaves as a 'closest point to surface' snap (at least in V18).
The distance between the point object in the DWG and the point found by BC is 0.10 units.
I do not know if it is inherent but perhaps it may be interesting:
V20 LISP
Added a BricsCAD-specific Lisp function (vl-vector-project-PointToEntity point viewDir entity) to calculate the point projected onto the "surface" of an entity. The function supports closed curves, 3DFace, 3DSolid, Region, Surface, PolyfaceMesh and PolygonMesh entities.

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
Here is my further analysis...
Roy can you check DWG I am attaching here with the results of BricsCAD...
Is ZPERpendicular SNAP point inside small green surface marked near preliminary point?
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
Here is my further analysis...
Roy can you check DWG I am attaching here with the results of BricsCAD...
Is ZPERpendicular SNAP point inside small green surface marked near preliminary point?

You are right Roy, ZPER snap in BricsCAD gives correct results, but how can we implement correct (vlax-surface-getclosestpointto surface wcspt) when ZPER finds all perpendiculars on surface - not only in small green surface I marked...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
Strangely AutoCAD 2018 also has ZPER OSNAP, but it won't SNAP to that point like BricsCAD is snapping... I don't know what to say - cumbersome ACAD... :(
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
ZPER finds all perpendiculars on surface - not only in small green surface I marked...
In my test (BricsCAD V18) only one point is found. It does not matter where you click the surface.

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Strangely AutoCAD 2018 also has ZPER OSNAP, but it won't SNAP to that point like BricsCAD is snapping...

Snaps to a perpendicular face (planar faces only).

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
ZPER finds all perpendiculars on surface - not only in small green surface I marked...
In my test (BricsCAD V18) only one point is found. It does not matter where you click the surface.

I tested it once again on BricsCAD V19 and you are right, only one point on surface, but on boundaries there are many... I'll attach *.DWG once more for you to see...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
Yes, I tested it once again without curves and yes you are right - only one ZPER snap... So discard my previous post...

Regards, M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8702
  • AKA Daniel
Here is my entry for Surface, should work in 2019-2020

Code: [Select]
(defun c:doit ( /)
  (setq p (getpoint "Where? "))
  (setq e (car(entsel)))
  (setq r (vlaxSurfaceGetClosestPointTo e p))
  (distance p r)
)

inspiration from Alexander Rivilis - https://adn-cis.org/forum/index.php?topic=59.msg4561#msg4561

edit added a module for BricsCAD V20
« Last Edit: October 30, 2019, 01:23:42 AM by It's Alive! »

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
Code: [Select]
: APPLOAD
Loading C:\                  TESTING ROUTINES\ArxBrxClosestPoint.brx
Error loading "C:\                  TESTING ROUTINES\ArxBrxClosestPoint.brx": .
C:\                  TESTING ROUTINES\ArxBrxClosestPoint.brx loading failed.
Loading C:\                  TESTING ROUTINES\ArxBrxClosestPoint.arx
Error loading "C:\                  TESTING ROUTINES\ArxBrxClosestPoint.arx": .
C:\                  TESTING ROUTINES\ArxBrxClosestPoint.arx loading failed.

Tried from BricsCAD V19.2.14 (x64)

BTW. I also have AutoCAD 2018 (x64), but not 2019, 2020... I suppose from your statement 2019-2020 that it won't arxload there either...

Also I would write test function like this :

Code: [Select]
(defun c:doit ( / surf pt )
  (while
    (or
      (not (setq surf (car (entsel "\nPick SURFACE..."))))
      (if surf
        (not (wcmatch (cdr (assoc 0 (entget surf))) "*SURFACE*"))
      )
    )
    (prompt "\nMissed or picked wrong entity type...")
    (textscr)
  )
  (initget 1)
  (setq pt (getpoint "\nPick or specify reference point : "))
  (entmake (list '(0 . "POINT") (cons 10 (vlaxsurfacegetclosestpointto surf (trans pt 1 0)))))
  (princ (cdr (assoc 10 (entget (entlast)))))
  (princ)
)
« Last Edit: October 30, 2019, 05:42:47 AM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8702
  • AKA Daniel
Try this one with V19

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8702
  • AKA Daniel
Also I would write test function like this :

mine only works with surfaces :)

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
Also I would write test function like this :

mine only works with surfaces :)

I've corrected test function...
Thanks it's working now with my BricsCAD...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8702
  • AKA Daniel
this one might work with surfaces, 3Dsolids and regions...
I changed the name from vlaxsurfacegetclosestpointto to getClosestPointTo
« Last Edit: October 30, 2019, 08:01:11 AM by It's Alive! »

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
this one might work with surfaces, 3Dsolids and regions...
I changed the name from vlaxsurfacegetclosestpointto to getClosestPointTo

Code: [Select]
(defun c:doit ( / f surf pt )
  (if (not (vl-position "arxbrxclosestpointv19.brx" (arx)))
    (progn
      (setq f (getfiled "Select ArxBrxClosestPointv19.brx file..." "\\" "brx" 16))
      (arxload f)
    )
  )
  (while
    (or
      (not (setq surf (car (entsel "\nPick SURFACE, or 3DSOLID, or REGION..."))))
      (if surf
        (not (wcmatch (cdr (assoc 0 (entget surf))) "*SURFACE*,3DSOLID,REGION"))
      )
    )
    (prompt "\nMissed or picked wrong entity type...")
    (textscr)
  )
  (initget 1)
  (setq pt (getpoint "\nPick or specify reference point : "))
  (entmake (list '(0 . "POINT") (cons 10 (getclosestpointto surf (trans pt 1 0)))))
  (princ (cdr (assoc 10 (entget (entlast)))))
  (princ)
)

Daniel, I need to know :
It's not possible or it's hard to do *.arx version for AutoCAD - say : 2014-2018 either for just surfaces or like you last did - surfaces, 3dsolids, regions?

If not possible, I may consider porting from Brics to Auto through scripting...
« Last Edit: October 30, 2019, 11:36:15 AM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8702
  • AKA Daniel
Yeah sure, should be easy. Does it work as advertised?, I only briefly tested on very simple objects.
I’ll post binaries and source in show my stuff in the next couple days

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8702
  • AKA Daniel
I don't have 2018, but try this one

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
Yeah sure, should be easy. Does it work as advertised?, I only briefly tested on very simple objects.
I’ll post binaries and source in show my stuff in the next couple days

And me too - tested on very simple objects and it works...

BTW. I already ported :

Code: [Select]
(defun c:zper ( / str+ surf es pt folder path f shell apphandle apphandle-b )

  (vl-load-com)

  (defun str+ ( source / prefix rchar )
    (cond
      ( (= source "") "A")
      ( (= (setq prefix (substr source 1 (1- (strlen source)))
                  rchar (substr source (strlen source))
            )
            "Z"
        )
        (strcat (str+ prefix) "A")
      )
      ( (strcat prefix (chr (1+ (ascii rchar)))))
    )
  )

  (while
    (or
      (not (setq surf (car (setq es (entsel "\nPick SURFACE, or 3DSOLID, or REGION...")))))
      (if surf
        (not (wcmatch (cdr (assoc 0 (entget surf))) "*SURFACE*,3DSOLID,REGION"))
      )
    )
    (prompt "\nMissed or picked wrong entity type...")
    (textscr)
  )
  (initget 1)
  (setq pt (getpoint "\nPick or specify reference point : "))
  (while (findfile (setq path (strcat "c:\\" (if (null folder) (setq folder (str+ "")) (setq folder (str+ folder)))))))
  (acet-file-mkdir path)
  (vl-cmdf "_.-WBLOCK" (strcat path "\\surf.dwg") "" "_non" '(0.0 0.0 0.0) surf "")
  (vl-cmdf "_.UNDO" "1")
  (setq f (open (strcat path "\\surf.scr") "w"))
  (write-line "(if (not (vl-position \"arxbrxclosestpointv19.brx\" (arx)))" f)
  (write-line "(progn" f)
  (write-line "(setq f (getfiled \"Select ArxBrxClosestPointv19.brx file...\" \"\\\\\" \"brx\" 16))" f)
  (write-line "(arxload f)" f)
  (write-line ")" f)
  (write-line ")" f)
  (write-line (strcat "(setq surf (car (nentselp (list " (rtos (car (cadr es)) 2 20) " " (rtos (cadr (cadr es)) 2 20) " " (rtos (caddr (cadr es)) 2 20) "))))") f)
  (write-line (strcat "(setq pt (list " (rtos (car pt) 2 20) " " (rtos (cadr pt) 2 20) " " (rtos (caddr pt) 2 20) "))") f)
  (write-line "(entmake (list '(0 . \"POINT\") (cons 10 (getclosestpointto surf (trans pt 1 0)))))" f)
  (write-line "_.-WBLOCK" f)
  (write-line (strcat "\"" path "\\surf-BCAD.dwg" "\"") f)
  (write-line "" f)
  (write-line "0,0,0" f)
  (write-line "_LAST" f)
  (write-line "" f)
  (write-line "_.QUIT" f)
  (write-line "_Y" f)
  (close f)
  (startapp "cmd.exe /C taskkill /IM \"rlm.exe\" /F")
  (vl-cmdf "_.DELAY" 2000)
  (setq shell (vlax-get-or-create-object "Wscript.Shell"))
  (setq apphandle (vlax-invoke-method shell 'Exec "c:\\Program Files (x86)\\Bricsys\\Bricsys Network License Manager\\rlm.exe"))
  (if (= (vlax-get-property apphandle 'Status) 0)
    (setq apphandle-b (vlax-invoke-method shell 'Exec (strcat "C:\\Program Files\\Bricsys\\BricsCAD V19 en_US\\bricscad.exe " path "\\surf.dwg" " /B " path "\\surf.scr")))
  )
  (while (= (vlax-get-property apphandle-b 'Status) 0))
  (vl-cmdf "_.INSERT" (strcat path "\\surf-BCAD.dwg") "_non" '(0.0 0.0 0.0))
  (while (< 0 (getvar 'cmdactive))
    (vl-cmdf "")
  )
  (vl-cmdf "_.EXPLODE" "_L")
  (while (< 0 (getvar 'cmdactive))
    (vl-cmdf "")
  )
  (vl-file-delete (strcat path "\\surf.dwg"))
  (vl-file-delete (strcat path "\\surf.scr"))
  (vl-file-delete (strcat path "\\surf-BCAD.dwg"))
  (acet-file-rmdir path)
  (vlax-invoke-method apphandle 'Terminate)
  (vlax-release-object apphandle)
  (vlax-release-object apphandle-b)
  (vlax-release-object shell)
  (vl-cmdf "_.-PURGE" "_B" "surf-BCAD" "_N")
  (princ (cdr (assoc 10 (entget (entlast)))))
  (princ)
)

So now you have to have BricsCAD V19 and any AutoCAD...
I'll check your *.arx nevertheless and see if it works for A2018...

Thanks again, M.R.
« Last Edit: October 30, 2019, 11:36:49 AM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
I've tested it on simple objects and it works and for A2018...

Thanks again, M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8702
  • AKA Daniel
Here's the source and builds 2013-2020, v18-v20
I can't verify that older versions for acad load, so if you see one that doesn't, let me know

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
I am using this occaison to wish you Happy Birthday, Daniel...

All the best and take care, M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8702
  • AKA Daniel
I am using this occaison to wish you Happy Birthday, Daniel...

All the best and take care, M.R.

Thank you  :-)

ahsattarian

  • Newt
  • Posts: 112
I Draw a point on that point and then  :



 
Code - Auto/Visual Lisp: [Select]
  1.       (command "point" po)
  2.        (setq point (entlast))
  3.        (command "projectgeometry" point "" sl "ucs")
  4.        (setq z (caddr (cdr (assoc 10 (entget (entlast))))))
  5.        (entdel (entlast))
  6.        (entdel point)



ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
@I owe you one...
Daniel, what's up ?
How are you now...
Long time no see...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube