4
$\begingroup$

I am trying to plot a simple polar plot with joined points:

conductance = {{0 Degree, 1}, {10 Degree, 1.3}, {20 Degree, 1.2}, 
  {30 Degree, 1.0}, {40 Degree, 1.1}, {50 Degree, 1.3}, {60 Degree, 1.2}
};

ListPolarPlot[conductance
  , Joined -> True, InterpolationOrder -> 2, Mesh -> Full
]

enter image description here

However Mathematica shows some discontinuities.

Essentially the question is related to Why does Plot leave gaps in the graph of a continuous function?.

The option Exclusions, which solves the problem in Plot function, is not available in ListPolarPlot. How could I get a continuous joined polar plot?

$\endgroup$
  • $\begingroup$ The same behavior occurs in examples in the docs. It also occurs for ListPlot. $\endgroup$ – Michael E2 Jun 16 '17 at 2:41
  • $\begingroup$ How about using PolarPlot on fn = Interpolation[conductance, InterpolationOrder -> 2];? $\endgroup$ – Michael E2 Jun 16 '17 at 2:43
1
$\begingroup$

Here is a Wolfram Language program that computes interpolations of the conductance data by various means. All the conductance data was transformed from Polar to Cartesian coordinates before interpolation. Only the best result was converted back to Polar coordinates.

    Catch[Module[{conductance = {{0 Degree, 1}, {10 Degree, 
      1.3}, {20 Degree, 1.2}, {30 Degree, 1.0}, {40 Degree, 
      1.1}, {50 Degree, 1.3}, {60 Degree, 1.2}}, xFormedData, if, ifs,
    nls = "\n\n", xVals, xMax, xMin, xRange,(*bsf,*)yVals, yMin, yMax,
    dist, param, deg = 3, knots, m, ctrlpts, uparam, kfun, mbasis, 
   bsPolar, 
   axisLabels = 
    CoordinateTransformData["Polar" -> "Cartesian", 
     "Mapping", {r, t}]},
  xf = xFormedData = 
    Map[CoordinateTransformData["Polar" -> "Cartesian", 
       "Mapping", #] &, Map[Reverse, conductance]];
  xVals = Map[First, xFormedData]; xMin = Min[xVals]; 
  xMax = Max[xVals];
  yVals = Map[Last, xFormedData]; yMin = Min[yVals]; yMax = Max[yVals];
  Print[nls, "XFormed Data:\n", xFormedData];
  Print@nls;
  Print@ListPlot[xFormedData, Joined -> True, 
    PlotLabel -> "Conductance data xFormed to {x, y} Coordinates", 
    AxesLabel -> axisLabels];
  if = Interpolation[xFormedData, InterpolationOrder -> deg];
  Print@nls;
  Print@ListPlot[Table[{x, if[x]}, {x, Map[First, xFormedData]}], 
    Joined -> True, 
    PlotLabel -> "Interpolated xFormed Conductance data", 
    AxesLabel -> axisLabels];
  ifs = Interpolation[xFormedData, Method -> "Spline"];
  Print@nls;
  Print@ListPlot[Table[{x, ifs[x]}, {x, Map[First, xFormedData]}], 
    Joined -> True, 
    PlotLabel -> "Spline Interpolated xFormed Conductance data", 
    AxesLabel -> axisLabels];
  Print@nls;
  Print@Graphics[{BSplineCurve[xFormedData], Green, Line[xFormedData],
      Red, Point[xFormedData]}, 
    PlotLabel -> "BSplineCurve Fitted to xFormed Conductance data", 
    AxesLabel -> axisLabels, Axes -> True];
  (* Points to bew interpolateed are xFormedData  *)
  (* Compute distances between control points     *)
  dist = Accumulate[
    Table[EuclideanDistance[xFormedData[[i]], 
      xFormedData[[i + 1]]], {i, Length[xFormedData] - 1}]];
  (* Compute normalized parameters wrt the distances (chord length \
parametrization) *)
  param = N[Prepend[dist/Last[dist], 0]];
  (* A cubic B-spline curve with clamped knots will be used *)
  knots = 
   Join[{0, 0, 0}, 
    Range[0, 1, 1/(Length[xFormedData] - deg)], {1, 1, 1}];
  (*Print["Knots: ",knots];*)
  (*  Set up the square basis matrix to solve: *)
  m = Table[
    BSplineBasis[{deg, knots}, j - 1, param[[i]]], {i, 
     Length[xFormedData]}, {j, Length[xFormedData]}];
  (*Print[MatrixForm[m]];*)
  (* Solve the linear system to get control points *)
  ctrlpts = LinearSolve[m, xFormedData];
  (*Print["CtrlPts: ",ctrlpts];*)
  (* Show the interpolating curve with the original data *)
  Print@nls;
  Print@Show[Graphics[BSplineCurve[ctrlpts, SplineDegree -> deg]],
    ListPlot[xFormedData, 
     PlotStyle -> Directive[Red, PointSize[Medium]]], Axes -> True, 
    AxesLabel -> axisLabels, ImageSize -> Large, 
    PlotLabel -> 
     "BSplineCurve Interpolation Fitted by Method Given in \
BSplineCurve Docs"];
  (* Use uniform parametrization  *)
  uparam[pts_] := N[Range[0, 1, 1/(Length[pts] - 1)]];
  (* Define a function to generate clamped knots for a given number \
of control points and degrees *)
  kfun[n_, d_] := 
   Join[ConstantArray[0, d], Range[0, 1, 1/(n - d)], 
    ConstantArray[1, d]];
  (* Define the basis matrix for least squares *)
  mbasis[pts_, n_, d_] := 
   With[{param2 = uparam[xFormedData]}, 
    Table[BSplineBasis[{d, kfun[n, d]}, j - 1, param2[[i]]], {i, 
      Length[param2]}, {j, n}]];
  (* A cubic B-
  spline curve with 7 control points will be used for fitting: *)
  ctrlpts = LeastSquares[mbasis[xFormedData, 7, deg], xFormedData];
  (* Show the data with the curve *)
  Print@nls;
  Print@ListPlot[xFormedData, Joined -> True, AxesLabel -> axisLabels,
     ImageSize -> Large, 
    PlotLabel -> 
     "BSplineCurve Fitted by Least Squares to xFormed Conductance \
data", Epilog -> {Red, BSplineCurve[ctrlpts, SplineDegree -> deg]}];
  bsf = BSplineFunction[xFormedData];
  Print@nls;
  Print@ParametricPlot[bsf[x], {x, 0., 1.}, 
    PlotLabel -> "BSplineFunction Fitted to xFormed Conductance Data",
     AxesLabel -> axisLabels, Axes -> True, 
    PlotRange -> {{xMin, xMax}, {yMin, yMax}}, 
    Epilog -> {Green, Line[xFormedData], Red, Point[xFormedData]}];
  (* Transform the data back from Cartesian to Polar coordinates *)
  bsPolar = 
   Map[Reverse, 
    Map[CoordinateTransformData["Cartesian" -> "Polar", 
       "Mapping", #] &, Table[bsf[x], {x, 0, 1, 0.01}]]];
  Print@nls;
  Off[MessageName[PolarAxes, "polarticks"]];
  Print@ListPolarPlot[{conductance, bsPolar}, Joined -> True, 
    PolarAxes -> True, Axes -> {True, False}, 
    PolarTicks -> Range[0, 350 Degree, 10 Degree],
    PlotLegends -> 
     Placed[{"Original Data", "BSpline Function"}, Below], 
    ImageSize -> 400, 
    PlotLabel -> 
     "BSpline Function Converted to Polar Coordinates and Original \
Data"]]]

The two interpolation methods given in the documentation for BSplineCurve obviously have Mean Squared Error (MSE) of zero since the interpolation goes through every point, but the first has negative conductances, and the second has a different order 3 polynomial in every segment between two points, which may not be realistic. Here they are though:

enter image description here

[2]

The next interpolation method uses the BSplineFunction command. This method is less accurate because the final curve does not pass exactly through each data point, but it is only one (or perhaps two) degree 3 polynomial (AFAIK) and hence may be more descriptive of what is actually going on with the data. In addition, it is possible to take derivatives of B-Spline curves at a point, if you need them.

enter image description here

Here is the last curve converted back to Polar coordinates and the original data:

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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