# Parellel-To-Plane Version of RegionDistance

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

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

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".

• 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? Commented Aug 15, 2022 at 14:51
• I tried experimenting with RegionNearest and taking [[3]] of it to compare it with Pz. Didnt manage it to take off. Commented Aug 15, 2022 at 17:37

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];
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.

## 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}]

## 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}]}]

## 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]

• 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. Commented Aug 15, 2022 at 15:48
• Yep, exactly. I will re-formulate my question. Commented Aug 15, 2022 at 17:39

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 *)
• Shouldn't InfinitePlane go through $P$ and not through $(0,0,0)$? Commented Aug 15, 2022 at 14:55
• Sure, you are right. I corrected my error. Commented Aug 15, 2022 at 15:51
• Wow, this seems to be what I desired. How does one implement the cheking if there's empty intersection? Commented Aug 15, 2022 at 17:45
• I added a piece that checks for a non empty intersection. Commented Aug 15, 2022 at 19:32