SINTEF / Splipy

Spline modelling made easy.
GNU General Public License v3.0
102 stars 18 forks source link

Adaptive Curve fitting #15

Closed VikingScientist closed 7 years ago

VikingScientist commented 7 years ago

Allows for non-uniform adaptive refinement of curve-fitting when you have available an exact solution; for instance with parametric curves.

VikingScientist commented 7 years ago

This was inspired by the need to drop the "resolution" keyword which I too often ended up with on parametric curves; see examples/lissajous.py or PR #12 . What I truly want to use this for is some of the more sophisticated techniques such as rewriting surface_factory.thicken()

def thicken(crv, thickness):
  def right(t):
    return crv(t) + thickness * crv.normal(t)
  def left(t):
    return crv(t) - thickness * crv.normal(t)
  c1 = curve_factory.fit(right, crv.start(0), crv.end(0))
  c2 = curve_factory.fit(left, crv.start(0), crv.end(0))
  return surface_factory.edge_curves(c1,c2)

Since one cannot represent the result from this operation exactly, it is only fitting that one does a clever approximation rather than keep the potentially inefficient old discretization.

While this is next up, the current patch can already do stuff such as this:

# approximates a difficult function with wild behaviour around t=0, but
# this is overcome by a higher knot density around this point
def one_over_t(t):
    t = np.array(t)
    eps = 1e-8 # to avoid 1/0 we add a small epsilon
    return np.array( [t, 1.0/(t+eps)] ).T
crv = curve_factory.fit(one_over_t, 0, 1, rtol=1e-6)
print crv

output:

p=4, [  0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00
   8.61166226e-09   1.72233245e-08   2.58349868e-08   3.44466490e-08
...
   6.50000000e-01   7.00000000e-01   7.50000000e-01   8.00000000e-01
   8.66666667e-01   9.33333333e-01   1.00000000e+00   1.00000000e+00
   1.00000000e+00   1.00000000e+00]
[[  0.00000000e+00   1.00000000e+08]
 [  2.87055409e-09   7.27880420e+07]
...
 [  9.77777778e-01   1.02222432e+00]
 [  1.00000000e+00   9.99999990e-01]]