I started getting into spline principles to use them in my studies. However, I got stuck in programming the code for Wikipedia [example] . The final graph doesn't correspond to the Wiki's example. I get two curves that are not connected, despite the introduction of the parameter t(x):
Spline segments
Would you mind helping me in finding the cause of the error? Thanks.
import numpy as np
import matplotlib.pyplot as plt
x0, y0, x1, y1, x2, y2 = -1, 0.5, 0, 0, 3, 3
def spline(x0, y0, x1, y1, x2, y2):
a11 = 2 / (x1 - x0)
a12 = 1 / (x1 - x0)
a13 = 0
a21 = a12
a22 = 2 * (1 / (x1 - x0) + 1 / (x2 - x1))
a23 = 1 / (x2 - x1)
a31 = a13
a32 = a23
a33 = 2 / (x2 - x1)
b1 = 3 * ((y1 - y0) / (x1 - x0) ** 2)
b2 = 3 * ((y1 - y0) / (x1 - x0) ** 2 + (y2 - y1) / (x2 - x1) ** 2)
b3 = 3 * ((y2 - y1) / (x2 - x1) ** 2)
A = np.array([[a11, a12, a13], [a21, a22, a23], [a31, a32, a33]])
L = np.array([[-b1], [-b2], [-b3]])
AT = np.transpose(A)
ATA = np.matmul(AT, A)
invATA = np.linalg.inv(ATA)
ATL = np.matmul(AT, L)
X = - np.matmul(invATA, ATL)
[k0, k1, k2] = X
a1 = k0 * (x1 - x0) - (y1 - y0)
b1 = -k1 * (x1 - x0) + (y1 - y0)
a2 = k1 * (x2 - x1) - (y2 - y1)
b2 = -k2 * (x2 - x1) + (y2 - y1)
return a1[0], b1[0], a2[0], b2[0]
a1, b1, a2, b2 = spline(-1, 0.5, 0, 0, 3, 3)
def q1(t):
return (1 - t) * y0 + t * y1 + t *(1 - t) * ((1 - t) * a1 + t * b1)
def q2(t):
return (1 - t) * y1 + t * y2 + t *(1 - t) * ((1 - t) * a2 + t * b2)
x_list = []
y1_list = []
y2_list = []
for x in range(1000):
t = (x/1000 - x1) / (x2 - x1)
x_list.append(x)
y1_list.append(q1(t))
y2_list.append(q2(t))
plt.scatter(x_list, y1_list)
plt.scatter(x_list, y2_list)
I found it! The key was the proper x-range corresponding to the 3 given points.
import numpy as np
import matplotlib.pyplot as plt
x0, y0, x1, y1, x2, y2 = -1, 0.5, 0, 0, 3, 3
def spline(x0, y0, x1, y1, x2, y2):
a11 = 2 / (x1 - x0)
a12 = 1 / (x1 - x0)
a13 = 0
a21 = a12
a22 = 2 * (1 / (x1 - x0) + 1 / (x2 - x1))
a23 = 1 / (x2 - x1)
a31 = a13
a32 = a23
a33 = 2 / (x2 - x1)
b1 = 3 * ((y1 - y0) / (x1 - x0) ** 2)
b2 = 3 * ((y1 - y0) / (x1 - x0) ** 2 + (y2 - y1) / (x2 - x1) ** 2)
b3 = 3 * ((y2 - y1) / (x2 - x1) ** 2)
A = np.array([[a11, a12, a13], [a21, a22, a23], [a31, a32, a33]])
L = np.array([[-b1], [-b2], [-b3]])
AT = np.transpose(A)
ATA = np.matmul(AT, A)
invATA = np.linalg.inv(ATA)
ATL = np.matmul(AT, L)
X = - np.matmul(invATA, ATL)
[k0, k1, k2] = X
a1 = k0 * (x1 - x0) - (y1 - y0)
b1 = -k1 * (x1 - x0) + (y1 - y0)
a2 = k1 * (x2 - x1) - (y2 - y1)
b2 = -k2 * (x2 - x1) + (y2 - y1)
return a1[0], b1[0], a2[0], b2[0]
a1, b1, a2, b2 = spline(-1, 0.5, 0, 0, 3, 3)
def q1(t):
return (1 - t) * y0 + t * y1 + t *(1 - t) * ((1 - t) * a1 + t * b1)
def q2(t):
return (1 - t) * y1 + t * y2 + t *(1 - t) * ((1 - t) * a2 + t * b2)
x1_list = []
x2_list = []
y1_list = []
y2_list = []
for x in range(-1000, 0, 1):
t = (x/1000 - x0) / (x1 - x0)
x1_list.append(x)
y1_list.append(q1(t))
for x in range(3000):
t = (x/1000 - x1) / (x2 - x1)
x2_list.append(x)
y2_list.append(q2(t))
plt.scatter(x1_list, y1_list)
plt.scatter(x2_list, y2_list)
I'm trying to construct a function to create a linear space, similar to python.
Just to start the function I create this code:
lin x0 x1 tam zero
| tam - zero > 0.0 = (x0 + (x1-x0)/tam) : x1
| otherwise = x1
but i'm getting this error message:
<interactive>:2:45: error:
• Occurs check: cannot construct the infinite type: a ~ [a]
• In the second argument of ‘(:)’, namely ‘x1’
In the expression: (x0 + (x1 - x0) / tam) : x1
In an equation for ‘lin’:
lin x0 x1 tam zero
| tam - zero > 0 = (x0 + (x1 - x0) / tam) : x1
| otherwise = x1
• Relevant bindings include
zero :: a (bound at <interactive>:1:15)
tam :: a (bound at <interactive>:1:11)
x1 :: a (bound at <interactive>:1:8)
x0 :: a (bound at <interactive>:1:5)
lin :: a -> a -> a -> a -> [a] (bound at <interactive>:1:1)
what am I doing wrong? And how could I fix it?
Since you use x1 on the right of a :, x1 must be a list of some sort. However you are also using x1 on the left of the : as if it were a number. It can't be both and that is why you get the error message
In more detail, the compiler has figured out that x0, x1, tam, and zero all have the same type, which it calls a and that that is the type of (x0 + (x1 - x0) / tam). Since the operand on the left of the : has type a, x must have type [a]. But x1 also has type a and so the compiler tries to unify a with [a], which it can't do.
I assume the intention is that x0 and x1 are numbers, right? But : constructs a list out of a first element and another list containing the rest of the elements. So in
{- ... -} : x1
you are treating the number x1 as if it were a list. Similarly, since one branch of the conditional returns a list, the other branch must, too, and your
| otherwise = x1
is interpreted as trying to return x1 as if it were a list.
On the other hand, if the intention from the start was that x1 should be a list, then the computation
x0 + (x1 - x0)/tam
(or, more specifically, x1 - x0) doesn't really make sense, because it appears to treat x1 as a number instead of a list.
I have 4 points and angle (as shown on the picture). How to get new point values for rotated object?
picture(x/y axis inverted, mistake. Vertical should be Y, horizontal - X)
At first, get coordinates relative to the rotation origin (x0, y0)
x' = x1 - x0
y' = y1 - y0
Then rotate
x'' = x' * Cos(Fi) - y' * Sin(Fi)
y'' = x' * Sin(Fi) + y' * Cos(Fi)
And now shift coordinates back
x_r = x'' + x0
y_r = y'' + y0
Given an input of two tupples, i want to be able to calculate the distance between two points using the formula:
distance = sqrt ( (x1 - x2) ^ 2 + (y1 - y2) ^2 )
so i want the function call and output to look like this:
-- > distance (5 , 10) (3 , 5)
-- 5.385...
when i try to run my code below, it tells me parse error on input 'where'. Can anyone help me resolve my issue? Here is my code:
distance (x1 , y1) (x2 , y2) = sqrt (x'*x' + y'*y')
where
x' = x1 - x2
y' = y1 - y2
You are making an indendation error, this should work- see how where clause is indented:
distance (x1 , y1) (x2 , y2) = sqrt (x'*x' + y'*y')
where
x' = x1 - x2
y' = y1 - y2
Can you see what is wrong with this:
(define (box d x1 y1 x2 y2) (
(graphics-draw-line d x1 y1 x1 y2)
(graphics-draw-line d x1 y2 x2 y2)
(graphics-draw-line d x2 y2 x2 y1)
(graphics-draw-line d x2 y1 x1 y1) ))
When I call it like this:
( begin
(define w (make-graphics-device 'x))
(box w .10 .10 .20 .20) )
I get an errer:
;The object #!unspecific is not applicable.
;To continue, call RESTART with an option number:
; (RESTART 2) => Specify a procedure to use in its place.
; (RESTART 1) => Return to read-eval-print level 1.
2 error>
This works:
(begin
(define w (make-graphics-device 'x))
(graphics-draw-line w .1 .1 .1 .2)
(graphics-draw-line w .1 .2 .2 .2)
(graphics-draw-line w .2 .2 .2 .1)
(graphics-draw-line w .2 .1 .1 .1) )
I can't see the difference!
Don't just group expressions with ()s -- that will try to use the result of the first as a function, but the value is #!unspecific -- definitely not a function.
Use this:
(define (box d x1 y1 x2 y2)
(graphics-draw-line d x1 y1 x1 y2)
(graphics-draw-line d x1 y2 x2 y2)
(graphics-draw-line d x2 y2 x2 y1)
(graphics-draw-line d x2 y1 x1 y1))