9
$\begingroup$

There are many built-in functions that return a function object, such as Interpolation[], BSplineFunction[] ,LinearSolveFunction[] and so on.

enter image description here


Now given that I want to build a function called CAGDBSplineFunction[] like the built-in BSplineFunction[] with the help of Cox-DeBoor algorithm.

First trial, please see here

To achieve the dynamic effect and check the validity of the option like the built-in BSplineFunction

enter image description here

I refactored it as below:

CAGDBSplineFunction::invknots = 
  "Value of option SplineKnots \[Rule] `1` should be a non-decreasing \
   real sequence of length `2`, or a symbol Automatic.";

Options[CAGDBSplineFunction] = 
  {SplineDegree -> Automatic, SplineKnots -> Automatic};

CAGDBSplineFunction /: 
 MakeBoxes[CAGDBSplineFunction[pts_, opts : OptionsPattern[]], _] := 
 Module[{n, sk, sd, range},
  n = Length@pts - 1;
  sk = OptionValue[SplineKnots];
  sd = OptionValue[SplineDegree];
  (*check the validity of the option SplineKnots*)
  If[sk =!= Automatic,
   If[n + 1 + sd != Length[sk] - 1, 
    Message[CAGDBSplineFunction::invknots, sk, n + 2 + sd];
    Return[$Failed]];
    range = Through[{First, Last}@sk],
   range = {0, 1}
  ]
 ]
 InterpretationBox[
   RowBox[{"CAGDBSplineFunction", "[", "{", #1, ",", #2, "}", ",", 
   "\"<>\"", "]"}], CAGDBSplineFunction[pts, opts]] & @@ range
]

TEST

pts = {{0, 0}, {1, 1}, {2, -1}, {3, 0}, {4, -2}, {5, 1}};
f = CAGDBSplineFunction[pts]

enter image description here

However, it seems that the option value cannot be achieved in a MakeBoxes construct.

J.M. gives me the following suggestion:

Don't try to do both display and processing at once. Set a definition for evaluating CAGDBSplineFunction[], and then set a definition for displaying, via MakeBoxes

According to the J.M.'s hint, I add the defintion to CAGDBSplineFunction[]

CAGDBSplineFunction /: 
 MakeBoxes[CAGDBSplineFunction[pts_, opts : OptionsPattern[]], _] := 
  InterpretationBox[
    RowBox[{"CAGDBSplineFunction", "[", "{", #1, ",", #2, "}", ",", 
  "\"<>\"", "]"}], CAGDBSplineFunction[pts, opts]] & @@ 
    CAGDBSplineFunction[pts, opts]

CAGDBSplineFunction[pts_, opts : OptionsPattern[]] :=
 Module[
  {n, sk, sd, range},
  n = Length@pts - 1;
  sk = OptionValue[SplineKnots];
  sd = OptionValue[SplineDegree] /. Automatic -> 3;
  (*check the validity of the option SplineKnots*)
  If[sk =!= Automatic,
   If[n + 1 + sd != Length[sk] - 1, 
    Message[CAGDBSplineFunction::invknots, sk, n + 2 + sd];
    Return[$Failed]];
    range = Through[{First, Last}@sk],
   range = {0, 1}
  ]
 ]

enter image description here

$\endgroup$
8
  • 3
    $\begingroup$ Something like constructor[pts_, deg_] := excecutor[someStructure[pts, deg]]; excecutor[someStructure[pts_, deg_]][t_] := doSomething[someStructure[pts, deg, t]]; myfun = constructor[{{1, 1}, {2, 2}}, 1]; myfun[t] ? $\endgroup$ Commented Oct 12, 2015 at 6:12
  • 2
    $\begingroup$ With respect to version 10-style output formatting of such functions, see this. $\endgroup$ Commented Oct 12, 2015 at 6:30
  • 1
    $\begingroup$ You coud try an approach similar to this. $\endgroup$ Commented Oct 12, 2015 at 7:45
  • 4
    $\begingroup$ (1) Construction: Define makemyfn[stuff_] to return object myfn[data]. (2) Format myfn with with MakeBoxes as in the linked questions in the comments. (3) Computation: Define sub-value myfn[datastructure_][input_] := (* computation *) for the computation, using whatever patterns for datastructure that are appropriate. -- Which is what belisarius said, but seems to have been ignored? $\endgroup$
    – Michael E2
    Commented Oct 12, 2015 at 10:25
  • 2
    $\begingroup$ You could separate the function that creates the function object from the function object itself. Interpolation is distinct from InterpolatingFunction. The insides of the latter are of no concern to users, thus there's no need to do syntax checking on them. $\endgroup$
    – Szabolcs
    Commented Oct 18, 2015 at 15:23

1 Answer 1

4
+100
$\begingroup$

It is not easy to show the domain dynamicly when the domain was been given by the option, for instance, in your function CAGDBSplineFunction,the option SplineKnots -> Automatic.

In the SphericalLinearInterpolation[], the range was given by the arguments, rather than the option. So it is easy to implement the dynamic domain by pure function.

MakeBoxes[SphericalInterpolatingFunction[range_, rest__], _] ^:= 
 InterpretationBox[
  RowBox[
   {"SphericalInterpolatingFunction", "[", "{", #1, ",",
     #2, "}", ",", "\"<>\"", "]"}], 
SphericalInterpolatingFunction[range, rest]] & @@ Map[ToBoxes, range]

To achieve the goal, you should reference the package Splines in your Mathematica install directory

XXX\Wolfram Research\Mathematica\9.0\AddOns\Packages\Splines

For instance, the following code can help you(Notice the defintion of the SubValues of SplineFunction[type, {min, max}, pts,internal])

Format[SplineFunction[t_,r_, b__]] :=
Row[{"SplineFunction[",t,", ", r,", ","<>","]"}]

SplineFunction[type_, {min_, max_}, pts_,internal_][in_?(NumberQ[N[#]]&)] :=
Module[{out},
    If[in < min || in > max,
        Message[SplineFunction::dmval, in];
        out = $Failed,
		(* else *)
			out = evalspline[
				 Which[in == max, Min[max, in],
					   in == min, Max[min, in],
					   True, in], type, pts, internal]
		];
		out/;out =!= $Failed
]

Format[CAGDBSplineFunction1[pts_, opts : OptionsPattern[]]] :=
 Module[{n, sk, range},
  sk = SplineKnots /. {opts} /. Options[CAGDBSplineFunction];
  If[sk === Automatic, 
    range = {0, 1}, 
    range = Through[{First, Last}@sk]
  ];
 Row[
   {"CAGDBSplineFunction1", "[", "{", sk, , ",", range, "}", ",", 
   "<>", "]"}]    
 ]

pts = {{0, 0}, {1, 1}, {2, -1}, {3, 0}, {4, -2}, {5, 1}};
CAGDBSplineFunction[pts, SplineKnots -> Range[0, 9]]

enter image description here

In addition, you should not use the OptionValue, rather than SplineKnots /. {opts} /. Options[CAGDBSplineFunction]

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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