Problems finding intersection points between line and generic function

I'm trying to find Intersection points between a line, which is given by 2 points, and a generic function (I want it to be able to handle polynomial functions, circles/ovals, lines and all combinations). The code works fine for some cases, but I'm in a world of hurt, if the line becomes vertical/horizontal.

1) How should I change the f[x] to allow lines to be vertical or horizontal. I don't allow P1=P2, so line is always defined.

(*Initial Settings*)
Clear["Global*"]
P1 = {-2, 2};
P2 = {2, -2};
f[x_] := (P1[] - P2[])/(P1[] - P2[]) (x - P1[]) +
P1[];
g[x_] := Piecewise[{{x^2, x <= 0}, {x, 0 < x < 1}, {x^2, x >= 1}}];
gr1 = Plot[f[x], {x, -6, 6}];
gr2 = Plot[g[x], {x, -6, 6}];
points = Graphics[{Red, PointSize[0.015], Point[P1], Point[P2]}];

(*Finding the solutions*)
IntersectionPointsX = x /. Solve[f[x] == g[x], Reals];
IntersectionPoints = {};
Do[AppendTo[
IntersectionPoints, {IntersectionPointsX[[k]],
f[IntersectionPointsX[[k]]]}], {k, Length[IntersectionPointsX]}];
If[Length[IntersectionPoints] > 0,
Show[gr1, gr2, points,
ListPlot[IntersectionPoints, PlotStyle -> PointSize[0.02]],
Axes -> True, PlotRange -> {{-6, 6}, {-6, 6}}, AspectRatio -> 1] ,
Show[gr1, gr2, points, Axes -> True, PlotRange -> {{-6, 6}, {-6, 6}},
AspectRatio -> 1] ]

If I choose these settings:

P1 = {-3.75, -4};
P2 = {-1.5, 0};
g[x_] := Piecewise[{{Undefined, x < -4}, {x, -4 < x < -2}, {Sqrt[
2^2 - (x)^2], -2 < x < 2}, {Undefined, x >= 2}}] I'm missing one solution. The problem is that g[x] "jumps" the right spot and the vertical line is only graphical, so the solve cant find it.

2) Is there an easy way to fix g[x] here, so I can solve for all intersections?

3) Using only half of the circle function isn't quite optimal either probably, but fixing that isn't a priority atm.

All general improvements to code also welcome of course, I have still a lot to learn.

EDIT:

I changed line function to parametric, which solved all horizontal/vertical problems I had earlier. Then I changed g[x] into parametric, using trivial settings of x=t But solve still doesn't find all solutions.

For example: w/o parameterization Mathematica finds both solutions

Clear["Global*"]
f[x_] := -x + 1;
g[x_] := Piecewise[{{x^2, x <= 0}, {x, True}}];
Solve[f[x] == g[x]]

{{x -> 1/2}, {x -> 1/2 (-1 - Sqrt)}}

then I parameterize and lose one point:

Clear["Global*"]
f[t1_] := {t1, -t1 + 1};
g[t2_] := Piecewise[{{{t2, t2^2}, t2 <= 0}, {{t2, t2}, True}}];
Solve[f[t1] == g[t2]]

{{t2 -> 1/2, t1 -> 1/2}}

Perhaps Piecewise isn't the best way to combine those parametric functions or my trivial parameterization is not good enough?

All comments are welcome and thanks for all answers!

• you should define f and g as parametric functions f[t1_]:={fx[t1],fy[t1]} and g[t2_]:={gx[t2],gy[t2]}, then solve the system of equations Solve[Thread[f[t1]==g[t2]],{t1,t2}] – k_v Mar 30 '15 at 16:10
• You can define at least the line parametrically, e.g. as p+t*p2 where p1, p2 are the points it goes through. Then set p+t*p2=={x,g[x]} and solve for x (you have two eqn in two unknowns). – Daniel Lichtblau Mar 30 '15 at 16:17
• Your last example is wrong, the vertical line between (-2,-2) and (-2,0) is a plot artifact, given that the function you define has a jump discontinuity in x=2. – enzotib Mar 30 '15 at 16:37
• @enzotib I Think I wasn't clear in my post. I know that the vertical jump discontinuity is plot artifact. But I would like to change the g[x] definition so, that the vertical part shown in plot would be part of it. That way solve can find a solution there. – Merrto Mar 30 '15 at 23:50
• Solve[PiecewiseExpand[f[t1] == g[t1]]]? – kglr Mar 31 '15 at 5:49

This could also be an example for InfinitLine. If your line is a vertical line the intersection is just the function value, i.e.{x,f[x]}. Given p1 = {1, 1}; p2 = {2, 3}; and

f[x_] := Sqrt[4 - x^2]

one can define

line = InfiniteLine[p1, p2]

and calculate the intersection points via

sols = NSolve[{x, y} \[Element] line \[And] {x, f[x]} \[Element] line]

I used NSolve for greater flexibility. Putting the parts together you can define a function:

showPlot[p1_, p2_, f_, {xmin_, xmax_}] :=  Module[{line = InfiniteLine[{p1, p2}], sols, pts},  sols = NSolve[{x, y} \[Element] line \[And] {x, f[x]} \[Element]  line];  If[p1[] == p2[], pts = {p1[], f[p1[]]},    pts = {x, y} /. sols];  Show[{Plot[f[x], {x, xmin, xmax}], Graphics@line,     Graphics[{PointSize[Medium], Red, Point[pts]}]}]  ]

and use it directly:

showPlot[p1, p2, f, {-2, 2}] Or wrap a Manipulate around:

g[x_] := x^3 - 2 x^2 + 3 x + 2

Manipulate[ showPlot[p1, p2, g, {-2, 2}], {{p1, {1, 1}}, Locator}, {{p2, {2, 1}},   Locator}] There is no missing point for the function as defined.

• g[-2] is not defined an returns undefined. Mathematica just joins.

• Plot[g[x], {x, -6, 6}, Exclusions -> {-2}] is the appropriate plot of function

• Consider also:

Limit[g[x], x -> -2, Direction -> 1]
Limit[g[x], x -> -2, Direction -> -1]

The following achieves aim of second set of points. The ham-fisted use of MapThread reflects difficulty of diplaying parametric plots in separate colours and lack of time.

p[t_] := Piecewise[{{2 {Cos[t], Sin[t]}, 0 < t < Pi}, {{-2, 2 Sin[t]},
Pi < t < Pi + Pi/2}, {{-2, -2} + 4/Pi (3 Pi/2 - t) {1, 1},
Pi + Pi/2 < t < 2 Pi}}]
h[t_] := With[{p1 = {-3.75, -4},
p2 = {-1.5, 0}}, (p2 - p1) t + p1] 