De Casteljau algorithm ignore a control point - python

I wrote an implementation of the De Casteljau algorithm to create a Bezier curve. My problem is the function ignores the second control point, it does calculate some kind of curve, but it is not correct.
def DeCasteljau(CNTRL_P, t):
ReP = points.point()
Ret = points.point()
n = len(CNTRL_P)
k = 0
tmp = 0
while k < n:
tmp = (((1 - t)**((n-1) - k)) * (t**k))
ReP.addP(CNTRL_P[k])
#ReP.Prnt()
ReP.mulP(tmp)
Ret.addP(ReP)
ReP.Clr() #ReP => (0,0)
tmp = 0
k = k + 1
return Ret
For example: CNTRL_P = [P0, P1, P2]
It ignores P1
class point():
def __init__(self, X = 0, Y = 0):
self.x = X
self.y = Y
def addP(self, P1):
self.x = self.x + (P1.getX())
self.y = self.y + (P1.getY())
def subP(self, C = 0, D = 0):
self.x = self.x - C
self.y = self.y - D
def mulP(self, C):
self.x = self.x * C
self.y = self.y * C
def getX(self):
a = self.x
return a
def getY(self):
a = self.y
return a
def Prnt(self):
print "X:", self.x,"Y:", self.y
def Clr(self):
self.x = 0
self.y = 0

Implementation looks faulty. Where's the recursion?
Does this give you better results?
def DeCasteljau2(CNTRL_P, t):
tmp_points = CNTRL_P[:]
while len(tmp_points) > 1:
for k in range(len(tmp_points)-1):
ReP = point()
ReP2 = point()
ReP.addP(tmp_points[k])
ReP2.addP(tmp_points[k+1])
ReP.mulP((1-t))
ReP2.mulP(t)
ReP.addP(ReP2)
tmp_points[k] = ReP
tmp_points.pop()
return tmp_points[0]
This is the result after each iteration:
P0 | P1 | P2
P0 * (1-t) + P1 * t | P1 * (1-t) + P2
(P0 * (1-t) + P1 * t)*(1-t) + (P1 * (1-t) + P2)*t
You repeat the algorithm until you only have 1 point left. Each point P(n) in the next solution is the result of P(n) * (1-t) + p(n+1) * t from the last solution. At each iteration the last point is discarded since there is no next point that you could multiply and add with.
Wikipedia probably can explain that better than me: link

Related

I have ray class and line class and want to find line-ray intersection point

I wrote classes for Ray, Line, Point, and some other shapes, but I was stopped by the need for a function that takes a Line class object and a Ray class object as a parameter, and returns the point at which the line and the ray intersect.
Point class:
class Point:
def __init__(self, x: float, y: float):
self.x = x
self.y = y
def __getitem__(self, index):
if index == 0:
return self.x
elif index == 1:
return self.y
def __iter__(self):
yield self.x
yield self.y
def __str__(self):
return f"x = {self.x}; y = {self.y}"
Ray class:
class Ray:
def __init__(self, start: Point, end: Point):
self.start = start
self.end = end
def get_direction(self):
x_diff = self.end[0] - self.start[0]
y_diff = self.end[1] - self.start[1]
return (x_diff, y_diff)
Line class:
class Line:
def __init__(self, point1: Point, point2: Point):
self.point1 = point1
self.point2 = point2
def get_direction(self) -> tuple:
x_diff = abs(self.point2[0] - self.point1[0])
y_diff = abs(self.point2[1] - self.point1[1])
return (x_diff, y_diff)
def get_params(self) -> tuple:
x1, y1 = self.point1
x2, y2 = self.point2
a = y2 - y1
b = x1 - x2
c = x2 * y1 - x1 * y2
return a, b, c
def get_normal(self):
a, b, c = self.get_params()
return -b, a, c
And perhaps the following functions can help:
Is the point on the line?
def point_on_line(point: Point, line: Line):
x1, y1 = line.point1
x2, y2 = line.point2
x, y = point
return (y - y1) * (x2 - x1) == (y2 - y1) * (x - x1)
Is the point on the ray?
def point_on_ray(point: Point, ray: Ray) -> bool:
start = ray.start
end = ray.end
direction = ray.get_direction()
x_diff = point[0] - start[0]
y_diff = point[1] - start[1]
if x_diff * direction[1] == y_diff * direction[0]:
if x_diff >= 0 and y_diff >= 0:
return True
return False
I am bad in Math so i asked ChatGPT to help me, but he wrote some functions which will return wrong result
I tried giving ChatGPT several completely different prompts, and I got several completely different functions in response, but anyway, they all didn't work. Some of them returned the wrong points, some of them thought the ray and the line were parallel, although they have not worked correctly
You have to solve equation system
ray.start.x + t * ray.diff.x = line.point1.x + u * line.diff.x
ray.start.y + t * ray.diff.y = line.point1.y + u * line.diff.y
for unknowns t and u, then check that t >= 0
Then substitute t value into the left parts to get intersection point coordinates.
Standalone Python function
def ray_line_intersection(rx0, ry0, rdiffx, rdiffy, lx0, ly0, ldiffx, ldiffy):
denom = ldiffy * rdiffx - ldiffx * rdiffy
if denom == 0: #ray and line are parallel or coincident
return (1) if (lx0 - rx0) * rdiffy == (ly0 - ry0) * rdiffx else None
t = (ldiffx * (ry0 - ly0) + ldiffy * (lx0 - rx0)) / denom
return (rx0 + rdiffx * t, ry0 + rdiffy * t) if t >=0 else None
print(ray_line_intersection(0, 0, 1, 1, 3, 0, -1, 1))
print(ray_line_intersection(0, 0, 1, 1, 3, 0, 1, 1))
print(ray_line_intersection(0, 0, 1, 1, -1, -1, 4, 4))
print(ray_line_intersection(0, 0, 1, 1, -1, 0, 1, -1))
>>> (1.5, 1.5) normal intersection
>>> None parallel
>>> 1 ray lies in the line
>>> None intersection beyond ray range

taking derivative using sparse matrix

I’m trying to solve the following problem for around 2 days, but have not had success.
I want to calculate the derivative using the sparse matrix, but the result doesn’t true. I think there is a mistake in the solution function, but I cannot find it.
class Cahn_Hillard(object):
def __init__(self, n, X, T, dt, skip):
self.n = n
self.X = X
self.dx = 1 / (n - 1)
self.T = T
self.dt = dt
self.N = int(self.T / self.dt)
def __call__(self):
central = self.forward_diff_sparse()
itr = int(self.T / self.dt)
for i in range(0, itr + 1):
if i == 0:
c = np.random.uniform(0, 1, (self.n, 1))
else:
c_next = self.solution(c, central)
c = c_next
print(i)
return c
def forward_diff_sparse(self):
sparse_mat = np.eye(self.n) - np.eye(self.n, k=-1)
return sparse_mat
def solution(self, c, central):
# calculate derivative of concentration
deriv = central.dot(c) / self.dx
# calculate difusion coeffcient
D_eff = (1 - 2 * self.X * c * (1 - c)) * deriv
Diff = central.dot(D_eff) / self.dx
# Calculate the next step concentration
next_c = c + self.dt * Diff
return next_c
It would be great if you help me.

Iterate every csv column and predict value using linear regression

I am using a loop to grab values from every csv row and run it through linear_regression_model for prediction. The needed output is, for every row in the csv, print the predicted value that ran through the model, like:
4.500
4.256
3.909
4.565
...
4.433
Here is what I did:
def prediction_loop():
for index, row in ml_sample.iterrows():
print(row['column'])
new_data = OrderedDict(['column', row])
new_data = pd.Series(new_data).values.reshape(1,-1)
print(linear_regression_model.predict(new_data))
The actual output I get is:
Traceback (most recent call last):
new_data = OrderedDict(['column', row])
ValueError: too many values to unpack (expected 2)
In the csv there are 87 rows and 1 column.
How can I optimise the code?
Thank you
If I understand the question correctly, then this can be done very efficiently without the aid of any external modules. We just need a trivial class to manage the statistics. The assumption is that the input file contains one numerical value per line and that such values are Y and the implied line number is X. Try this:-
class Stats():
def __init__(self):
self.n = 0
self.sx = 0
self.sy = 0
self.sxx = 0
self.syy = 0
self.sxy = 0
def add(self, x, y):
self.sx += x
self.sy += y
self.sxx += x * x
self.syy += y * y
self.sxy += x * y
self.n += 1
def r(self): # correlation coefficient
return (self.n * self.sxy - self.sx * self.sy) / ((self.n * self.sxx - self.sx * self.sx) * (self.n * self.syy - self.sy * self.sy)) ** 0.5
def b(self): # slope
return (self.n * self.sxy - self.sx * self.sy) / (self.n * self.sxx - self.sx * self.sx)
def a(self): # intercept
return self.my() - self.b() * self.mx()
def mx(self): # mean x
assert self.n > 0
return self.sx / self.n
def my(self): # mean y
assert self.n > 0
return self.sy / self.n
def y(self, x): # estimate of y for given x
return x * self.b() + self.a()
stats = Stats()
with open('lr.txt') as data:
for i, line in enumerate(data):
stats.add(i, float(line.split()[0]))
print(f'r={stats.r():.4f} slope={stats.b():.4f} intercept={stats.a():.4f}')
for x in range(stats.n):
print(f'Estimate for {x} = {stats.y(x):.2f}')

Methods with keywords from the instances's attributes

The perfect, but impossible, scenario would be:
class example(object):
def __init__(self,x,y):
self.x = x
self.y = y
def foo(self, x = self.x, y = self.y):
return x + y
It doesn't work because self isn't defined. I have done lots of research, looked on decorators, descriptors, metaclasses, almost everything. The solution may be the most obvious and known to all, but I couldn't find it. I could manage two workarounds, as follows:
def prep(argslist, argsprovided, attributes):
argsout = []
for name in argslist:
if name in argsprovided:
argsout.append(argsprovided[name])
else:
argsout.append(getattr(attributes,name))
return argsout
class example(object):
# I can create a default instance or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
# I can wrap a function to use the self argument
def wrapper(self):
def foo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
return foo
# I can wrap 'joo' alongside with foo, and make 'wrapper' return a list
def joo(self, **kwargs):
[x,y,z,w] = prep(['x','y','z','w'],kwargs,self)
return x + y + z + 2*w
# I can use my custom 'prep' function to to the job
def foo(self, **kwargs):
[x,y,z,w] = prep(['x','y','z','w'],kwargs,self)
return x + y + z + w
# Creates a default instance and a custom one
c = example()
d = example(2,2,2,2)
# I can use 'foo' with the instance's default values with both wrapping and 'prepping'
print(c.wrapper()())
print(d.wrapper()())
print(c.foo())
print(d.foo())
# I can use 'foo' with a mix of default values and provided values with both wrapping and 'prepping'
print(c.wrapper()(1,2,3))
print(d.wrapper()(1,2,3))
print(c.foo(y = 3,z = 4,w = 5))
print(d.foo(y = 3,z = 4,w = 5))
The code prints out:
4
8
4
8
7
8
13
14
I have a huge class with lots of functions, every one needs the behavior of 'foo'. My prep solution is too time consuming. After profiling the code, I figured it spent 12 seconds inside prep only. What is a clever and less time consuming way of doing this? I'm completely lost.
I'm not sure it will help but how about using None as a default value and use a clause to determine the value. For example:
def foo(self, x=None, y=None):
real_x = x if x != None else self.x
real_y = y if y != None else self.y
return real_x + real_y
I found six ways of doing what I wanted. After profiling the code, the result was:
afoo foo noo1 noo2 wrap1 wrap2
6.730 28.507 3.98 4.097 10.256 3.468
6.407 28.659 4.096 3.924 9.783 3.529
6.277 28.450 3.946 3.889 10.265 3.685
6.531 30.287 3.964 4.149 10.077 3.674
As you will see ahead, noo1, noo2 and wap2 are quite similar on code. The conventional method afoo is not that efficient. My custom method foo is terrible and wrap1 was just tested for the sake of completeness.
afoo.py
The drawback is that you need an extra line for each function argument.
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def afoo(self, x = None, y = None, z = None, w = None):
x = x if x != None else self.x
y = y if y != None else self.y
z = z if z != None else self.z
w = w if w != None else self.w
return x + y + z + w
c = example(2,2,2,2)
for i in range(0, 10000000):
c.afoo(1,2,3,4)
foo.py
This one is the slower method.
def prep(argslist, argsprovided, attributes):
argsout = []
for name in argslist:
if name in argsprovided:
argsout.append(argsprovided[name])
else:
argsout.append(getattr(attributes,name))
return argsout
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def foo(self, **kwargs):
[x,y,z,w] = prep(['x','y','z','w'],kwargs,self)
return x + y + z + w
c = example(2,2,2,2)
for i in range(0, 10000000):
c.foo(x = 1,y = 2,z = 3,w = 4)
wrapper1.py
By far less efficient than wrapper2.py.
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def wrapper(self):
def foo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
return foo
c = example(2,2,2,2)
for i in range(0, 10000000):
c.wrapper()(1,2,3,4)
wrapper2.py
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def wrapper(self):
def foo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
return foo
c = example(2,2,2,2)
k = c.wrapper()
for i in range(0, 10000000):
k(1,2,3,4)
noo1.py
class example(object):
# I can create a default class or a custom one
def __init__(self,U,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def noo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
self.noo = noo
c = example(2,2,2,2)
for i in range(0, 10000000):
c.noo(1,2,3,4)
noo2.py
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def __call__(self):
def noo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
self.noo = noo
c = example(2,2,2,2)
c()
for i in range(0, 10000000):
c.noo(1,2,3,4)
When testing these codes I included the prep function in all of them, just to be shure they had the same basic structure, and thus the time difference would be from the loops.

Overriding the plus operator for a user defined vector class in Python

I have written a class to work with three dimensional vectors as follows
class vector(object):
def __init__(self, x=None, y=None, z=None, angle=None):
if angle == None:
self.x, self.y, self.z = x, y, z
if angle != None:
if angle == "rad":
self.r, self.theta, self.phi = x, y, z
if angle == "deg":
self.r = x
self.theta = y * 2 * pi / 360.
self.phi = z * 2 * pi / 360.
self.x = self.r * sin(self.theta) * cos(self.phi)
self.y = self.r * sin(self.theta) * sin(self.phi)
self.z = self.r * cos(self.theta)
def write(self):
file.write("[" + str(self.x) + ",\t" + str(self.y) + ",\t" + str(self.z) + "]")
def write_sph(self):
file.write("[" + str(self.mag()) + ",\t" + str(self.gettheta()) + ",\t" + str(self.getphi()) + "]")
def getx(self):
return self.x
def gety(self):
return self.y
def getz(self):
return self.z
def setx(self, x):
self.x = x
def sety(self, y):
self.y = y
def setz(self, z):
self.z = z
def square(self):
return self.x*self.x + self.y*self.y + self.z*self.z
def mag(self):
return sqrt(self.square())
def gettheta(self):
return arccos(self.z / self.mag())
def getphi(self):
return arctan2(self.y, self.x) # sign depends on which quadrant the coordinates are in
def __add__(self, vector(other)):
v_sum = vector(other.gettx() + self.gettx(), other.getty() + self.getty(), other.getty() + self.getty())
return v_sum
In the last definition I am attempting to override the operator for addition. The definition works by calling a new vector named other and adding its x,y,z components to the corresponding components of self. When I run the code I'm told the syntax for the definition is invalid. How do I correctly define the vector argument for this overriding definition? Also what difference would changing the definition from def __ add __ to simply def add make? i.e what do the underscores denote?
You shouldn't have vector(other) in your parameter list - just say other. Also, you'll need to fix the typos in the add method:
def __add__(self, other):
v_sum = vector(other.getx() + self.getx(), other.gety() + self.gety(), other.getz() + self.getz())
return v_sum

Categories

Resources