Rough approximation via plotting
V9: One can estimate the length of the polygonal path in the ContourPlot
from the graphics. It's a little easier to process if I adapt Daniel Lichtblau's (undocumented?) use of BoundaryStyle
in his answer to
Plotting implicitly-defined space curves. If the points in the plot lie exactly on the intersection, the length should be a lower bound on the true arc length. Since the points are not, we should expect some error.
contourplot =
ContourPlot3D[{h, g}, {x, -4, 4}, {y, -4, 4}, {t, -4, 4}, Contours -> {0},
ContourStyle -> Opacity[0], Mesh -> None,
BoundaryStyle -> {1 -> None, 2 -> None, {1, 2} -> {{Black}}},
Boxed -> False]

Norm /@ Differences@
First@Cases[Normal@contourplot, Line[p_] :> p, Infinity] // Total
(* 10.9512 *)
V10: The above does not work in V10. One can use {g == 0, h == 0}
instead of Contours -> {0}
, but the performance is about ten times slower (~11 sec. in V10) than in V9. Here's similar way that is faster:
Needs["GeneralUtilities`"];
contourplot =
ContourPlot3D[{g == 0}, {x, -4, 4}, {y, -4, 4}, {t, -4, 4},
PlotPoints -> 35, MaxRecursion -> 4,
MeshFunctions -> {Function[{x, y, t}, Evaluate@h]}, Mesh -> {{0}},
ContourStyle -> None, BoundaryStyle -> None, Boxed -> False,
Axes -> None,
WorkingPrecision -> $MachinePrecision]; // AccurateTiming
Norm /@ Differences @ First @ Cases[Normal@contourplot, Line[p_] :> p, Infinity] // Total
(*
0.17347 (* timing *)
10.9508 (* length *)
*)
By comparison DiscretizeRegion@RegionIntersection[ImplicitRegion[g == 0,..], ...]
takes an amazing 20 seconds. Probably these function will be developed for general usefulness in the future.
Integration via NDSolve
With NDSolve
we can integrate the speed of a parametrization over the segment of the curve in the plot region. One thing we need is a starting point on the curve. If Solve
fails to give us one, we can get them from the contour plot in this way:
endpoints = First@Cases[Normal@contourplot, Line[p_] :> p[[{1, -1}]], Infinity]
(* {{4., -1.00395, -1.00125}, {-1.77835, 4., 4.}} *)
In this case, Solve
works, and we'll use the first point where x == 4
. (One could also use FindRoot
.) Another we need is a starting velocity that points into the plot region. We can get a tangent vector from the cross product of the gradient vectors of the two surfaces. We will set up a differential equation for a unit speed parametrization, so we normalize the cross product. The direction is chosen by looking at the sign of the dot product of the tangent vector with the outward normal of the boundary of the plot region, that is, the vector {1, 0, 0}
which is normal to x == 4
. Finally we'll useWhenEvent
to stop the integration when the parameterization leaves the plot region.
bdynormal = {1, 0, 0}; (* start at x == 4 *)
startpoint = {x, y, t} /. First@Solve[{h == 0, g == 0, x == 4}, {x, y, t}];
startvelocity = -Sign[Dot[#, bdynormal]] Normalize[#] &@ (
Cross[D[h, {{x, y, t}}], D[g, {{x, y, t}}]] /. Thread[{x, y, t} -> startpoint]);
dae = {
h == 0 /. v : x | y | t :> v[u], (* constrains solution to h == 0 *)
g == 0 /. v : x | y | t :> v[u], (* constrains solution to g == 0 *)
Sqrt[#.# &@{x'[u], y'[u], t'[u]}] == 1}; (* unit speed *)
ics = {{x[0], y[0], t[0]} == startpoint,
{x'[0], y'[0], t'[0]} == startvelocity}; (* used by NDSolve to pick which root
of the dae to follow *)
reg = Cuboid[{-4, -4, -4}, {4, 4, 4}]; (* the plot region *)
s = NDSolveValue[{
dae, ics,
arclength'[u] ==
Sqrt[#.# &@{x'[0], y'[0], t'[0]}], arclength[0] == 0,
WhenEvent[! RegionMember[reg, {x[u], y[u], t[u]}], "StopIntegration"],
arclength, {u, 0, Infinity}];
s[s["Domain"][[-1, -1]]]
Solve::ifun: Inverse functions are being used by Solve, so some solutions may not be found; use Reduce for complete solution information. >>
(* 10.9513 *)
Discretize*
functions still are, they're not very good options for numerics except for very rough approximations. $\endgroup$Plot
-type precision, when discretized. It's nice to able to set up code in these terms though, say for graphical illustrations. $\endgroup$MaxCellMeasure
not working wasn't fixed in 10.0.1, that would have helped a bit with precision. $\endgroup$