1

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[[2]] - P2[[2]])/(P1[[1]] - P2[[1]]) (x - P1[[1]]) + 
   P1[[2]];
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}}]

enter image description here

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.

Thanks in advance.

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[5])}}

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!

Merrto
  • 11
  • 4
  • 1
    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+tp2wherep1,p2are the points it goes through. Then set ``p+tp2=={x,g[x]}and solve forx` (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 05:49

2 Answers2

1

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[[1]] == p2[[1]], pts = {p1[[1]], f[p1[[1]]]},    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}]

enter image description here

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

enter image description here

mgamer
  • 5,593
  • 18
  • 26
0

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]
sol = MapThread[
   t /. First[Quiet@Solve[#1 == h[s] && #2, {s, t}]] &, {p[t][[1, ;; ,
       1]], p[t][[1, ;; , 2]]}];
Show[MapThread[
  ParametricPlot[#1, {t, 0, 2 Pi}, PlotRange -> {-4, 4}, 
    PlotStyle -> #2, 
    Epilog -> {Red, PointSize[0.02], Point[p[#]] & /@ sol}] &, {{p[t],
     h[t]}, {Orange, Black}}]]

enter image description here

ubpdqn
  • 60,617
  • 3
  • 59
  • 148