# How can I deduce the distance formula from a point to a straight line?

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?

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] *)

• In the first line of your code a != 0 is implicitly assumed. You'll see the difference, making use of Reduce instead of Solve. Commented Sep 2, 2023 at 19:29
• @user64494 OK, I've added a rigorous solution, see my update. Commented Sep 3, 2023 at 0:44
• 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. Commented Sep 3, 2023 at 3:35
• @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. Commented Sep 3, 2023 at 3:49
• 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]. Commented Sep 3, 2023 at 4:15

Another workaround:

First a visualization of a selected instance:

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


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

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]

• -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)))}. Commented Sep 3, 2023 at 3:43

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

• 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. Commented Sep 3, 2023 at 4:56
• @xzczd: Why do you think so? My answer is RealAbs[(c + a*x0 + b*y0)]/Sqrt[(a^2 + b^2)]. Commented Sep 3, 2023 at 5:22
• 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[…]. Commented Sep 3, 2023 at 5:34
• @xzczd: You are right. Commented Sep 3, 2023 at 5:46