5
$\begingroup$

RegionDistance basically calculates distance between points P and Q=RegionNearest[Reg,P]:

RegionDistance

I need to find a way to find function of distance parallel to XY plane:

Directional RegionDiatance

And, I need it to operate in the way RegionDistance does, so that something like DirectionalRegionDistance[Reg] would give a distance function that could be applied repeatedly to different points.

Could someone help me out with this please ?

Upd: The original question was misleadingly formulated. I don't need "distance in a known direction". Instead, I need function that outputs sort of "distance parallel to plane", or, alternative naming - "distance perpenducular to a vector".

$\endgroup$
2
  • 1
    $\begingroup$ For the first part, I can envision the following: 1) Construct an InfiniteLine passing through $p$ and parallel to the direction you need. 2) Find RegionIntersection between the line and your object. 4) Calculate EuclideanDistances between all intersection points and your point $p$, and take the shortest. The second part, i.e. the distance function, seems orders of magnitude more complex. What have you tried so far? $\endgroup$
    – MarcoB
    Aug 15, 2022 at 14:51
  • $\begingroup$ I tried experimenting with RegionNearest and taking [[3]] of it to compare it with Pz. Didnt manage it to take off. $\endgroup$
    – Anton
    Aug 15, 2022 at 17:37

3 Answers 3

7
$\begingroup$

This is a crude implementation using RegionIntersection together with InfinitePlane.

DirectionalRegionDistance[reg_, v1_, v2_][p_] := 
 Module[{line, intersection},
  line = InfinitePlane[p, {v1, v2}];
  intersection = RegionIntersection[reg, line];
  If[Head@intersection === EmptyRegion, Infinity,
   RegionNearest[intersection, p]
   ]
  ]

reg = Sphere[];
p = {3/2, 3/2, 1/3};

(* Distance in XY plane *)
DirectionalRegionDistance[reg, {1, 0, 0}, {0, 1, 0}][p]
(* {2/3, 2/3, 1/3} *)

(* Distance in YZ plane *)
DirectionalRegionDistance[reg, {0, 0, 1}, {0, 1, 0}][p]
(* Infinity *)

This function takes a region reg, and two plane vectors v1 and v2.

$\endgroup$
5
$\begingroup$

Edit

For arbitrary normal of hyperplane.

Clear[reg, normal, pt, dist, sol, pt1];
reg = Ball[];
normal = {.1, -0.2, 1};
(* normal={0,0,1} *)
pt = {3, 4, .5};
dist = SignedRegionDistance[reg];
sol = NMinimize[{EuclideanDistance[{x, y, z}, 
    pt], {x, y, z} ∈ Hyperplane[normal, pt], 
   dist@{x, y, z} <= 0}, {x, y, z}]
pt1 = {x, y, z} /. sol[[2]]
Graphics3D[{Opacity[.95], reg, {Opacity[.6], Hyperplane[normal, pt]}, 
  Blue, AbsolutePointSize[8], Point[pt], Red, AbsolutePointSize[8], 
  Arrow[{pt, pt1}]}, ViewPoint -> {3, -1, 1}]

enter image description here

Two-dimensional conditional restrictions problem

Clear[reg, h, pt, dist, sol, pt1];
reg = Ball[];
h = .5;
pt = {2, 2, h};
dist = SignedRegionDistance[reg];
sol = NMinimize[{EuclideanDistance[{x, y, h}, pt], 
   dist@{x, y, h} <= 0}, {x, y}, Method -> "DifferentialEvolution"]
pt1 = {x, y, h} /. sol[[2]]
Graphics3D[{Opacity[.95], 
  reg, {Opacity[.2], InfinitePlane[pt, {{1, 0, 0}, {0, 1, 0}}]}, Blue,
   AbsolutePointSize[8], Point[pt], Red, AbsolutePointSize[8], 
  Arrow[{pt, pt1}]}]

enter image description here

One-dimensional conditional restrictions problem

We use NDSolve to descript the path from one point pt along the direction dir,and use WhenEvent to find such t0.

Clear[reg, pt, pt1, dir, sol, t0];
reg = Ball[];
pt = {2, 2, 2};
dir = Normalize@{-1.3, -2.1, -2};
dist = SignedRegionDistance[reg];
sol = Reap@
   NDSolve[{{x'[t], y'[t], z'[t]} == dir, {x[0], y[0], z[0]} == pt, 
     WhenEvent[
      dist@{x[t], y[t], z[t]} == 0, {Sow@t, "StopIntegration"}]}, {x, 
     y, z}, {t, 0, 10}];
t0 = sol[[2, 1, 1]];
pt1 = TranslationTransform[t0*dir]@pt;
Show[Graphics3D[{Opacity[.8], reg, Blue, AbsolutePointSize[8], 
   Point[pt], Point@pt1, Red, Arrow[{pt, pt1}]}], 
 ParametricPlot3D[TranslationTransform[t*dir]@pt, {t, 0, t0}, 
  PlotStyle -> Red], PlotRange -> All]

enter image description here

$\endgroup$
2
  • $\begingroup$ I think you might have misunderstood the OP's question (first, I did it too, it's a slightly misleading naming). He doesn't want a distance in a specific direction, but parallel to some plane. Therefore, your dir is actually unknown. $\endgroup$
    – Domen
    Aug 15, 2022 at 15:48
  • $\begingroup$ Yep, exactly. I will re-formulate my question. $\endgroup$
    – Anton
    Aug 15, 2022 at 17:39
4
$\begingroup$

We can still use "RegionDistance" if we calculate the intersection between the x-y plane and your region.

E.g. if we define r1 as a ball at {0,2,0} :

r1 = Region[Ball[{2, 0, 0}, 1]];

we may define a distance function that delivers the distance parallel to the x-y plane:

dist = (RegionDistance[RegionIntersection[r1,Region[InfinitePlane[{{0, 0, #[[3]]}, {1, 0, #[[3]]}, {0, 
          1, #[[3]]}}]]]][#]) &

If we apply this to the origin:

dist[{0,0,0}]
(* 1 *)

And if we apply it to the point: {0,1,0}:

dist[{0, 1, 0}]
(* Sqrt[2 (3 - Sqrt[5])] *)

Or:

dist[{0, 0, 1/2}]
(* 1/2 Sqrt[19 - 8 Sqrt[3]] *)

Note that it does not evaluate if the intersection has dimension 0.

If you want to check, if there is an non empty intersection, it becomes slightly more complex. We may e.g. first define a function that returns a function which returns either the distance or "Not available" if the intersection is empty:

getfun[reg_] := Module[{inter, dist},
  (inter = 
     RegionIntersection[reg, 
      Region[InfinitePlane[{{0, 0, #[[3]]}, {1, 0, #[[3]]}, {0, 
          1, #[[3]]}}]]];
    Switch[dist = RegionDistance[Evaluate@inter, #], _?NumberQ, 
     dist, _, "Not available"]) &
  ];

This will return a function that gives the horizontal distance to a point or "not available". E.g. the distance from a point {0,1,0.4} to the above ball:

dist = getfun[Region[Ball[{2, 0, 0}, 1]]];
dist[{0, 1, 0.4}]
(* 1.31955 *)
$\endgroup$
4
  • $\begingroup$ Shouldn't InfinitePlane go through $P$ and not through $(0,0,0)$? $\endgroup$
    – Domen
    Aug 15, 2022 at 14:55
  • $\begingroup$ Sure, you are right. I corrected my error. $\endgroup$ Aug 15, 2022 at 15:51
  • $\begingroup$ Wow, this seems to be what I desired. How does one implement the cheking if there's empty intersection? $\endgroup$
    – Anton
    Aug 15, 2022 at 17:45
  • $\begingroup$ I added a piece that checks for a non empty intersection. $\endgroup$ Aug 15, 2022 at 19:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.