B-spline

From Rosetta Code
Revision as of 16:10, 2 September 2021 by PureFox (talk | contribs) (Added closing lang tag to Julia example.)
B-spline is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Task

Generate a B-spline curve with a list of 12 points and plot or save image.

Coordinates of control points:

   start=171,171 
   1 185,111, 
   2 202,109, 
   3 202,189 
   4 328,160 
   5 208,254 
   6 241,330 
   7 164,252 
   8 69,278 
   9 139,208 
   10 72,148 
   end=168,172


Rules!!!!

Do not use third party libraries or functions

See also




Julia

Choose BSpline D of 2, ie degree 1. <lang julia>using Graphics, Plots

Point(t::Tuple) = Vec2(Float64(t[1]), Float64(t[2])) const controlpoints = Point.([(171, 171), (185, 111), (202, 109), (202, 189), (328, 160),

   (208, 254), (241, 330), (164,252), (69, 278), (139, 208), (72, 148), (168, 172)])

plt = plot(map(a -> a.x, controlpoints), map(a -> a.y, controlpoints)) savefig(plt, "BSplineplot.png")</lang>

Wren

Library: DOME

In the absence of any clarification on what to use (see Talk page), the following uses a degree of 3 (i.e order k = 4) and a uniform knot vector from 1 to 16 (as there are 12 control points) with a delta of 1.

If one uses a value for k of 1, then the script will simply plot the control points as in the Julia example. <lang ecmascript>import "dome" for Window, Process import "graphics" for Canvas, Color

class BSpline {

   construct new(width, height, cpoints, k) {
       Window.resize(width, height)
       Canvas.resize(width, height)
       Window.title = "B-spline curve"
       _p = cpoints
       _n = cpoints.count - 1
       _k = k
       _t = (1.._n + 1 + k).toList // use a uniform knot vector, delta = 1
   }
   // B-spline helper function
   w(i, k, x) { (_t[i+k] != _t[i]) ? (x - _t[i]) / (_t[i+k] - _t[i]) : 0 }
       
   // B-spline function
   b(i, k, x) {
       if (k == 1) return (_t[i] <= x  &&  x < _t[i + 1]) ? 1 : 0
       return w(i, k-1, x) * b(i, k-1, x) + (1 - w(i+1, k-1, x)) * b(i+1, k-1, x)
   }
   // B-spline points
   p() {
       var bpoints = []
       for (x in _t[_k-1]..._t[_n + 1]) {
           var sumX = 0
           var sumY = 0
           for (i in 0.._n) {
               var f = b(i, _k, x)
               sumX = sumX + f * _p[i][0]
               sumY = sumY + f * _p[i][1]
           }
           bpoints.add([sumX.round, sumY.round])
        }
        return bpoints
   }
   init() {
       if (_k > _n + 1 || _k < 1) {
           System.print("k (= %(_k)) can't be more than %(_n+1) or less than 1.")
           Process.exit()
       }
       var bpoints = p()
       // plot the curve
       for (i in 1...bpoints.count) {
           Canvas.line(bpoints[i-1][0], bpoints[i-1][1], bpoints[i][0], bpoints[i][1], Color.white)
       }
   }
   update() {}
   draw(alpha) {}

}

var cpoints = [

   [171, 171], [185, 111], [202, 109], [202, 189], [328, 160], [208, 254],
   [241, 330], [164, 252], [ 69, 278], [139, 208], [ 72, 148], [168, 172]

] var k = 4 // polynomial degree is one less than this i.e. cubic var Game = BSpline.new(400, 400, cpoints, k)</lang>