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$
  • 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$ – Dr. belisarius Oct 12 '15 at 6:12
  • 2
    $\begingroup$ With respect to version 10-style output formatting of such functions, see this. $\endgroup$ – J. M.'s technical difficulties Oct 12 '15 at 6:30
  • 1
    $\begingroup$ You coud try an approach similar to this. $\endgroup$ – J. M.'s technical difficulties Oct 12 '15 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 Oct 12 '15 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 Oct 18 '15 at 15:23
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

|improve this answer|||||
$\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.