3
$\begingroup$

Consider:

Clear["Global`*"]
reg = ImplicitRegion[a x + b y + c == 0, {x, y}]
pt = {x0, y0}
RegionDistance[reg, pt]

The distance formula from a point to a straight line cannot be derived using the above code.

Without knowing how to solve it, I attempted to replace it with the following code through other means:

Clear["Global`*"]
line=a x+b y+c==0
pt={x0,y0}
pol=Apply[Subtract,line];
Flatten@CoefficientList[pol,{x,y}];
A1=Coefficient[pol,x];
B1=Coefficient[pol,y];
C1=Select[pol,FreeQ[x|y]];
distance=Abs[A1 pt[[1]]+B1 pt[[2]]+C1]/Sqrt[A1^2+B1^2]

How can I change the first code to achieve the goal?

$\endgroup$

4 Answers 4

5
$\begingroup$

If we check the examples in document of RegionDistance, we'll see most of the examples are about specific graphic primitives (Line, Disk, etc.). This isn't too surprising, because functions like ImplicitRegion are so general, and general problems are always hard to handle. This inspires us to try replacing the ImplicitRegion with an InfiniteLine as a workaround:

ptfunc[y_] = {x /. Solve[a x + b y + c == 0, {x}][[1]], y}
(* {(-c - b y)/a, y} *)

reg = InfiniteLine[ptfunc /@ {0, 1}]
(* InfiniteLine[{{-(c/a), 0}, {(-b - c)/a, 1}}] *)

pt = {x0, y0};
dis = RegionDistance[reg, pt]
(* Sqrt[(c + a x0 + b y0)^2/(a^2 + b^2)] *)

dis // FullSimplify[#, {a, b, c, x0, y0} ∈ Reals] &
(* Abs[c + a x0 + b y0]/Sqrt[a^2 + b^2] *)

Update

As pointed out by user64494 in comment below, I've implicitly assumed a!=0 in the solution above, so let me add a rigorous and simpler solution making use of 2nd syntax of Hyperplane:

reg = Hyperplane[{a, b}, -c];

pt = {x0, y0};
dis = RegionDistance[reg, pt]
(* Abs[(c + a x0 + b y0)/Sqrt[a^2 + b^2]] *)

dis // Simplify[#, {a, b} ∈ Reals] &
(* Abs[c + a x0 + b y0]/Sqrt[a^2 + b^2] *)
$\endgroup$
9
  • $\begingroup$ In the first line of your code a != 0 is implicitly assumed. You'll see the difference, making use of Reduce instead of Solve. $\endgroup$
    – user64494
    Commented Sep 2, 2023 at 19:29
  • $\begingroup$ @user64494 OK, I've added a rigorous solution, see my update. $\endgroup$
    – xzczd
    Commented Sep 3, 2023 at 0:44
  • $\begingroup$ I think the formula Abs[(c + a x0 + b y0)/Sqrt[a^2 + b^2]] is simply implemented in RegionDistance, not derived there. The above is not any "a rigorous and simpler solution". Compare with my answer. $\endgroup$
    – user64494
    Commented Sep 3, 2023 at 3:35
  • $\begingroup$ @user64494 That depends on how we define "deduce"/"derive". Since OP has used RegionDistance in his first trial, I think using RegionDistance fits OP's requirement. $\endgroup$
    – xzczd
    Commented Sep 3, 2023 at 3:49
  • $\begingroup$ Hyperplane, up to its documentation, allows a==0&&b==0 (see "Hyperplane represents the set ... " and the next line in Details). Also reg=Hyperplane[{0, 0}, -c] results in Hyperplane[{0, 0}, -c]. $\endgroup$
    – user64494
    Commented Sep 3, 2023 at 4:15
4
$\begingroup$

Another workaround:

First a visualization of a selected instance:

enter image description here

Derivation:

pt = {x0, y0};
line = a x + b y + c == 0;
tri = Triangle[{pt
   , {0, y} /. First@Solve[line, y] /. {x -> 0}
   , {x, 0} /. First@Solve[line, x] /. {y -> 0}
   }]

Triangle[{{x0, y0}, {0, -(c/b)}, {-(c/a), 0}}]

ans = (TriangleMeasurement[tri, {"Height", pt}]) // 
  FullSimplify[#, {a, b, c, x0, y0} ∈ Reals] & (* `FullSimplify` step copied from xzczd's answer*)

Abs[c + a x0 + b y0]/Sqrt[a^2 + b^2]

which after (unnecessary) formatting becomes:

ans /. {x0 -> Subscript[x, 0], y0 -> Subscript[y, 0]} // 
 Map@TraditionalForm

enter image description here

$\endgroup$
2
  • $\begingroup$ Solve produces only a generic solution, not taking into consideration all possibilities of parameter values. Compare with my answer. $\endgroup$
    – user64494
    Commented Sep 3, 2023 at 3:46
  • $\begingroup$ In particular, you don't consider the cases when line is parallel to x-axis or y-axis. $\endgroup$
    – user64494
    Commented Sep 3, 2023 at 5:48
3
$\begingroup$

Given a point and a line:

pt={x0,y0}
line= a x+b y+c==0;

If we project the point: pt={x,y} perpendicularly onto the line we have the point: pp on the line closest to pt, giving the distance of the point from the line. Therefore, we have 2 equations one that pp={xp,yp} is on the line. The second comes from: pt-p0 is perpendicular to the direction of the line. Therefor, the scalar product from a vector in direction of the line and (pt-pp) must be zero

pt={x,y};
pp= {xp,yp};

The direction of the line: A vector perpendicular to the line is: {a,b}. Therefore, the direction is: {-b,a} (check: take the scalar product {a,b}.{-b,a})

dir= {-b,a}

Therefore we have 2 equations to determine pp:

eq = {{a, b} . pp + c == 0, dir. (pp - pt) == 0 }

And we get pp by:

ppsol= pp /. Solve[eq, {xp, yp}];

With this we get the distance:

Norm[pt -ppsol]

We can put all together in a distance function:

dist[pt_, {a_, b_, c_}] := 
 Module[{pp = {xp, yp}, dir = {-b, a}, eq, ppsol}, 
  eq = {{a, b} . pp + c == 0, dir . (pt - pp) == 0};
  ppsol = pp /. Solve[eq, pp][[1]]; 
  Norm[pt - ppsol]
  ]

Now, let us try if this works. A line from {0,1} to {1,0} has {a,b,c}=={1,1,-2} and a point {1,1} has a distance of 2/Sqrt[2] from this line:

dist[{2, 2}, {1, 1, -2}]

1/Sqrt[2]
$\endgroup$
1
  • $\begingroup$ -1. The result of ppsol is {(1/(2 (a^2 + b^2)))(-2 a c - a b p0 + b^2 p0 + b^2 x - a b y + \[Sqrt]((2 a c + a b p0 - b^2 p0 - b^2 x + a b y)^2 - 4 (a^2 + b^2) (c^2 + b c p0 + b^2 p0 x + b c y + b^2 p0 y))), (1/b)(-c + (a^2 c)/(a^2 + b^2) + (a^2 b p0)/( 2 (a^2 + b^2)) - (a b^2 p0)/(2 (a^2 + b^2)) - (a b^2 x)/( 2 (a^2 + b^2)) + (a^2 b y)/(2 (a^2 + b^2)) - (1/(2 (a^2 + b^2))) a \[Sqrt]((2 a c + a b p0 - b^2 p0 - b^2 x + a b y)^2 - 4 (a^2 + b^2) (c^2 + b c p0 + b^2 p0 x + b c y + b^2 p0 y)))}. $\endgroup$
    – user64494
    Commented Sep 3, 2023 at 3:43
1
$\begingroup$

Here is a direct approach which demonstrates the difficulties caused by 5 parameters $a,b,c,x0,y0$.

Minimize[{Sqrt[({x, y} - {x0, y0}) . ({x, y} - {x0, y0})], 
a*x + b*y + c == 0 && a^2 + b^2 > 0}, {x, y}] // First

Piecewise[{{Sqrt[x0^2], (x0 == 0 && c == 0 && a > 0 && b == 0) || (x0 == 0 && c == 0 && a < 0 && b == 0)}, {Sqrt[(c + a*x0)^2/a^2], (x0 > 0 && a > 0 && b == 0) || (x0 > 0 && a < 0 && b == 0) || (x0 < 0 && a > 0 && b == 0) || (x0 < 0 && a < 0 && b == 0)}, {Sqrt[(c^2 + a^2*x0^2)/a^2], (x0 == 0 && c > 0 && a > 0 && b == 0) || (x0 == 0 && c > 0 && a < 0 && b == 0) || (x0 == 0 && c < 0 && a > 0 && b == 0) || (x0 == 0 && c < 0 && a < 0 && b == 0)}, {Sqrt[(c + b*y0)^2/b^2], (x0 > 0 && a == 0 && b > 0) || (x0 > 0 && a == 0 && b < 0) || (x0 < 0 && a == 0 && b > 0) || (x0 < 0 && a == 0 && b < 0)}, {Sqrt[(c + a*x0 + b*y0)^2/(a^2 + b^2)], (x0 < 0 && a < 0 && b > 0) || (x0 > 0 && a > 0 && b > 0) || (x0 > 0 && a > 0 && b < 0) || (x0 > 0 && a < 0 && b > 0) || (x0 > 0 && a < 0 && b < 0) || (x0 < 0 && a > 0 && b > 0) || (x0 < 0 && a > 0 && b < 0) || (x0 < 0 && a < 0 && b < 0)}, {Sqrt[x0^2 + y0^2], (x0 == 0 && c == 0 && a == 0 && b > 0) || (x0 == 0 && c == 0 && a == 0 && b < 0)}, {Sqrt[(c^2 + a^2*x0^2 + b^2*x0^2 + 2*b*c*y0 + b^2*y0^2)/(a^2 + b^2)], (x0 == 0 && c > 0 && a > 0 && b > 0) || (x0 == 0 && c > 0 && a > 0 && b < 0) || (x0 == 0 && c > 0 && a < 0 && b > 0) || (x0 == 0 && c > 0 && a < 0 && b < 0) || (x0 == 0 && c < 0 && a > 0 && b > 0) || (x0 == 0 && c < 0 && a > 0 && b < 0) || (x0 == 0 && c < 0 && a < 0 && b > 0) || (x0 == 0 && c < 0 && a < 0 && b < 0)}, {Sqrt[x0^2 + (b^2*y0^2)/(a^2 + b^2)], (x0 == 0 && c == 0 && a > 0 && b > 0) || (x0 == 0 && c == 0 && a > 0 && b < 0) || (x0 == 0 && c == 0 && a < 0 && b > 0) || (x0 == 0 && c == 0 && a < 0 && b < 0)}, {Sqrt[x0^2 + y0^2 + (c*(c + 2*b*y0))/b^2], (x0 == 0 && c > 0 && a == 0 && b > 0) || (x0 == 0 && c > 0 && a == 0 && b < 0) || (x0 == 0 && c < 0 && a == 0 && b > 0) || (x0 == 0 && c < 0 && a == 0 && b < 0)}}, Infinity]

Its execution takes more than dozen minutes.

FullSimplify[%, Assumptions -> a^2 + b^2 > 0 && {a, b, x0, y0} ∈ Reals]

Piecewise[{{0, b == 0 && c == 0 && x0 == 0}, {Sqrt[(c + a*x0)^2/a^2], b == 0 && x0 != 0}, {Sqrt[c^2/a^2], b == 0 && x0 == 0 && c != 0}, {Sqrt[(c + b*y0)^2/b^2], a == 0 && (c != 0 || x0 != 0)}, {Sqrt[(c + a*x0 + b*y0)^2/(a^2 + b^2)], a != 0 && b != 0 && x0 != 0}, {Abs[y0], a == 0 && c == 0 && x0 == 0}, {Sqrt[(c + b*y0)^2/(a^2 + b^2)], x0 == 0 && a != 0 && b != 0 && c != 0}}, (Abs[b]*Abs[y0])/Sqrt[a^2 + b^2]]

At last,

FullSimplify[Piecewise[{{0, b == 0 && c == 0 && x0 == 0}, {Sqrt[(c + a*x0)^2/a^2], 
    b == 0 && x0 != 0}, {Sqrt[c^2/a^2], 
 b == 0 && x0 == 0 && c != 0}, 
  {Sqrt[(c + b*y0)^2/b^2], a == 0 && (c != 0 || x0 != 0)}, 
  {Sqrt[(c + a*x0 + b*y0)^2/(a^2 + b^2)], 
 a != 0 && b != 0 && x0 != 0}, 
  {Abs[y0], a == 0 && c == 0 && x0 == 0}, 
  {Sqrt[(c + b*y0)^2/(a^2 + b^2)], 
 x0 == 0 && a != 0 && b != 0 && 
      c != 0}}, (Abs[b]*Abs[y0])/Sqrt[a^2 + b^2]] - 
  Sqrt[(c + a*x0 + b*y0)^2/(a^2 + b^2)], 
 Assumptions -> a^2 + b^2 > 0 && {a, b, x0, y0} ∈ Reals]

0

FullSimplify[Sqrt[(c + a*x0 + b*y0)^2/(a^2 + b^2)] - 
RealAbs[(c + a*x0 + b*y0)]/Sqrt[(a^2 + b^2)], 
 Assumptions -> a^2 + b^2 > 0 && {a, b, x0, y0} ∈ Reals]

0

$\endgroup$
4
  • $\begingroup$ Please notice that, if the goal of the question is "obtaining the same output as the second sample", your answer doesn't meet the requirement. $\endgroup$
    – xzczd
    Commented Sep 3, 2023 at 4:56
  • $\begingroup$ @xzczd: Why do you think so? My answer is RealAbs[(c + a*x0 + b*y0)]/Sqrt[(a^2 + b^2)]. $\endgroup$
    – user64494
    Commented Sep 3, 2023 at 5:22
  • $\begingroup$ But the RealAbs[(c + a*x0 + b*y0)]/Sqrt[(a^2 + b^2)] is obtained by manual analysis, right? With FullSimplify, we only obtain a lengthy Piecewise[…]. $\endgroup$
    – xzczd
    Commented Sep 3, 2023 at 5:34
  • $\begingroup$ @xzczd: You are right. $\endgroup$
    – user64494
    Commented Sep 3, 2023 at 5:46

Your Answer

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

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