Find control point on piecewise quadratic Bezier curve - bezier

I need to write a program to generate and display a piecewise quadratic Bezier curve that interpolates each set of data points (I have a txt file contains data points). The curve should have continuous tangent directions, the tangent direction at each data point being a convex combination of the two adjacent chord directions.
0.1 0,
0 0,
0 5,
0.25 5,
0.25 0,
5 0,
5 5,
10 5,
10 0,
9.5 0
The above are the data points I have, does anyone know what formula I can use to calculate control points?

You will need to go with a cubic Bezier to nicely handle multiple slope changes such as occurs in your data set. With quadratic Beziers there is only one control point between data points and so each curve segment much be all on one side of the connecting line segment.
Hard to explain, so here's a quick sketch of your data (black points) and quadratic control points (red) and the curve (blue). (Pretend the curve is smooth!)
Look into Cubic Hermite curves for a general solution.

From here: http://blog.mackerron.com/2011/01/01/javascript-cubic-splines/
To produce interpolated curves like these:
You can use this coffee-script class (which compiles to javascript)
class MonotonicCubicSpline
# by George MacKerron, mackerron.com
# adapted from:
# http://sourceforge.net/mailarchive/forum.php?thread_name=
# EC90C5C6-C982-4F49-8D46-A64F270C5247%40gmail.com&forum_name=matplotlib-users
# (easier to read at http://old.nabble.com/%22Piecewise-Cubic-Hermite-Interpolating-
# Polynomial%22-in-python-td25204843.html)
# with help from:
# F N Fritsch & R E Carlson (1980) 'Monotone Piecewise Cubic Interpolation',
# SIAM Journal of Numerical Analysis 17(2), 238 - 246.
# http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
# http://en.wikipedia.org/wiki/Cubic_Hermite_spline
constructor: (x, y) ->
n = x.length
delta = []; m = []; alpha = []; beta = []; dist = []; tau = []
for i in [0...(n - 1)]
delta[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i])
m[i] = (delta[i - 1] + delta[i]) / 2 if i > 0
m[0] = delta[0]
m[n - 1] = delta[n - 2]
to_fix = []
for i in [0...(n - 1)]
to_fix.push(i) if delta[i] == 0
for i in to_fix
m[i] = m[i + 1] = 0
for i in [0...(n - 1)]
alpha[i] = m[i] / delta[i]
beta[i] = m[i + 1] / delta[i]
dist[i] = Math.pow(alpha[i], 2) + Math.pow(beta[i], 2)
tau[i] = 3 / Math.sqrt(dist[i])
to_fix = []
for i in [0...(n - 1)]
to_fix.push(i) if dist[i] > 9
for i in to_fix
m[i] = tau[i] * alpha[i] * delta[i]
m[i + 1] = tau[i] * beta[i] * delta[i]
#x = x[0...n] # copy
#y = y[0...n] # copy
#m = m
interpolate: (x) ->
for i in [(#x.length - 2)..0]
break if #x[i] <= x
h = #x[i + 1] - #x[i]
t = (x - #x[i]) / h
t2 = Math.pow(t, 2)
t3 = Math.pow(t, 3)
h00 = 2 * t3 - 3 * t2 + 1
h10 = t3 - 2 * t2 + t
h01 = -2 * t3 + 3 * t2
h11 = t3 - t2
y = h00 * #y[i] +
h10 * h * #m[i] +
h01 * #y[i + 1] +
h11 * h * #m[i + 1]
y

Related

Correlation of error terms in time-series model

I am reading this statistics book where they have mentioned that the attached top plot has no correlation between adjacent residuals. Whereas, the bottom most has correlation with p-0.9. Can anybody please provide some direction as to how to analyze this? Thank you very much for your time.
Correlated errors mean that the lag 1 correlation is p. That is, Cor(Yi, Yi-1) = p. This can be modelled using Yi = mu + p epsiloni-1 + epsiloni where epsiloni ~ N(0, 1) for all i. We can verify that the correlation between adjacent data points is p: Cov(Yi, Yi-1) = Cov(p epsiloni-1 + epsiloni, p epsiloni-2 + epsiloni-1) = Cov(p epsiloni-1, epsiloni-1) = p Var(epsiloni-1) = p. Code to demonstrate appears below:
set.seed(123)
epsilonX <- rnorm(100, 0, 1)
epsilonY <- rnorm(100, 0, 1)
epsilonZ <- rnorm(100, 0, 1)
X <- NULL
Y <- NULL
Z <- NULL
Y[1] <- epsilonY[1]
X[1] = epsilonX[1]
Z[1] = epsilonZ[1]
rhoX = 0
rhoY = 0.5
rhoZ = 0.9
for (i in 2:100) {
Y[i] <- rhoY * epsilonY[i-1] + epsilonY[i]
X[i] <- rhoX * epsilonX[i-1] + epsilonX[i]
Z[i] <- rhoZ * epsilonZ[i-1] + epsilonZ[i]
}
param = par(no.readonly = TRUE)
par(mfrow=c(3,1))
plot(X, type='o', xlab='', ylab='Residual', main=expression(rho*"=0.0"))
abline(0, 0, lty=2)
plot(Y, type='o', xlab='', ylab='Residual', main=expression(rho*"=0.5"))
abline(0, 0, lty=2)
plot(Z, type='o', xlab='', ylab='Residual', main=expression(rho*"=0.9"))
abline(0, 0, lty=2)
#par(param)
acf(X)
acf(Y)
acf(Z)
Note from the acf plots that the lag 1 correlation is insignificant for p = 0, higher for p = 0.5 data (~0.3), and still higher for p = 0.9 data (~0.5).

RGB to HSV in numpy

I'm trying to implement RGB to HSV conversion from opencv in pure numpy using formula from here:
def rgb2hsv_opencv(img_rgb):
img_hsv = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HSV)
return img_hsv
def rgb2hsv_np(img_rgb):
assert img_rgb.dtype == np.float32
height, width, c = img_rgb.shape
r, g, b = img_rgb[:,:,0], img_rgb[:,:,1], img_rgb[:,:,2]
t = np.min(img_rgb, axis=-1)
v = np.max(img_rgb, axis=-1)
s = (v - t) / (v + 1e-6)
s[v==0] = 0
# v==r
hr = 60 * (g - b) / (v - t + 1e-6)
# v==g
hg = 120 + 60 * (b - r) / (v - t + 1e-6)
# v==b
hb = 240 + 60 * (r - g) / (v - t + 1e-6)
h = np.zeros((height, width), np.float32)
h = h.flatten()
hr = hr.flatten()
hg = hg.flatten()
hb = hb.flatten()
h[(v==r).flatten()] = hr[(v==r).flatten()]
h[(v==g).flatten()] = hg[(v==g).flatten()]
h[(v==b).flatten()] = hb[(v==b).flatten()]
h[h<0] += 360
h = h.reshape((height, width))
img_hsv = np.stack([h, s, v], axis=-1)
return img_hsv
img_bgr = cv2.imread('00000.png')
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
img_rgb = img_rgb / 255.0
img_rgb = img_rgb.astype(np.float32)
img_hsv1 = rgb2hsv_np(img_rgb)
img_hsv2 = rgb2hsv_opencv(img_rgb)
print('max diff:', np.max(np.fabs(img_hsv1 - img_hsv2)))
print('min diff:', np.min(np.fabs(img_hsv1 - img_hsv2)))
print('mean diff:', np.mean(np.fabs(img_hsv1 - img_hsv2)))
But I get big diff:
max diff: 240.0
min diff: 0.0
mean diff: 0.18085355
Do I missing something?
Also maybe it's possible to write numpy code more efficient, for example without flatten?
Also I have hard time finding original C++ code for cvtColor function, as I understand it should be actually function cvCvtColor from C code, but I can't find actual source code with formula.
From the fact that the max difference is exactly 240, I'm pretty sure that what's happening is in the case when both or either of v==r, v==g are simultaneously true alongside v==b, which gets executed last.
If you change the order from:
h[(v==r).flatten()] = hr[(v==r).flatten()]
h[(v==g).flatten()] = hg[(v==g).flatten()]
h[(v==b).flatten()] = hb[(v==b).flatten()]
To:
h[(v==r).flatten()] = hr[(v==r).flatten()]
h[(v==b).flatten()] = hb[(v==b).flatten()]
h[(v==g).flatten()] = hg[(v==g).flatten()]
The max difference may start showing up as 120, because of that added 120 in that equation. So ideally, you would want to execute these three lines in the order b->g->r. The difference should be negligible then (still noticing a max difference of 0.01~, chalking it up to some round off somewhere).
h[(v==b).flatten()] = hb[(v==b).flatten()]
h[(v==g).flatten()] = hg[(v==g).flatten()]
h[(v==r).flatten()] = hr[(v==r).flatten()]

Can't figure out, why script on Jython working differently from script on Pascal

Long story short: I'm writing script, which should move mouse and do clicks like human (it's a bot, actually), using SikuliX. SikuliX uses Jython 2.7 as lang for scritps.
I found nice lib for my purposes (moving mouse like human): mouse.simba written in Pascal-like lang, and rewrite function _humanWindMouse() in jython. It works, but not like I expected it would be.
Test run of my script, drawing rectangle:
https://prtscr.cx.ua/storage/5b/5b2203.jpg
Result of using original function with same coords:
https://prtscr.cx.ua/storage/bb/bb3ff5.jpg
sorry for links, I can't post images yet (
My code:
import random
import time
import math
from time import sleep
from math import sqrt
from math import ceil
from math import hypot
from java.awt import Robot
def distance(x1, y1, x2, y2):
return math.hypot(x2 - x1, y2 - y1)
def myrandom(x):
return random.randint(0, x-1)
def myround(x):
return int(round(x))
# function MMouseMove (MyMouseMove) for moving mouse using only coord
def MMouseMove(x,y):
robot = Robot()
robot.mouseMove(x,y)
# function HumanWindMouse by BenLand100 & Flight, python implementation
def humanWindMouse(xs, ys, xe, ye, gravity, wind):
veloX = veloY = windX=windY=veloMag=dist=randomDist=lastDist=D=0
lastX=lastY=MSP=W=TDist=0
mouseSpeed = 20
MSP = mouseSpeed
sqrt2 = sqrt(2)
sqrt3 = sqrt(3)
sqrt5 = sqrt(5)
TDist = distance(myround(xs), myround(ys), myround(xe), myround(ye))
t = time.time() + 10000
while True:
if time.time() > t:
break
dist = hypot(xs - xe, ys - ye)
wind = min(wind, dist)
if dist < 1:
dist = 1
D = (myround((myround(TDist)*0.3))/7)
if D > 25:
D = 25
if D < 5:
D = 5
rCnc = myrandom(6)
if rCnc == 1:
D = random.randint(2,3)
if D <= myround(dist):
maxStep = D
else:
maxStep = myround(dist)
windX= windX / sqrt2
windY= windY / sqrt2
veloX= veloX + windX
veloY= veloY + windY
veloX= veloX + gravity * (xe - xs) / dist
veloY= veloY + gravity * (ye - ys) / dist
if hypot(veloX, veloY) > maxStep:
temp = int(myround(maxStep) // 2)
if temp == 0:
temp = 1
randomDist= maxStep / 2.0 + myrandom(temp)
veloMag= sqrt(veloX * veloX + veloY * veloY)
veloX= (veloX / veloMag) * randomDist
veloY= (veloY / veloMag) * randomDist
lastX= myround(xs)
lastY= myround(ys)
xs= xs + veloX
ys= ys + veloY
if lastX <> myround(xs) or lastY <> myround(ys):
MMouseMove(myround(xs), myround(ys))
W = (myrandom((myround(100/MSP)))*6)
if W < 5:
W = 5
W = myround(W*0.9)
sleep(W/1000.0)
lastdist= dist
if hypot(xs - xe, ys - ye) < 1:
break
if myround(xe) <> myround(xs) or myround(ye) <> myround(ys):
MMouseMove(myround(xe), myround(ye))
mouseSpeed = MSP
return;
def MMouse(x,y):
mouseSpeed = 20
randSpeed = (myrandom(mouseSpeed) / 2.0 + mouseSpeed) / 10.0
curPos = Mouse.at()
x1 = curPos.x
y1 = curPos.y
humanWindMouse(x1, y1, x, y, 5, 10.0/randSpeed)
return;
And I used this in such a way:
MMouseMove(227, 146)
mouseDown(Button.LEFT)
MMouse(396, 146)
MMouse(396, 252)
MMouse(227, 252)
MMouse(227, 146)
mouseUp(Button.LEFT)
exit()
mouseDown() and mouseUp() are built-in functions in SikuliX
And I didn't use built-in mouseMove(), because with it going from A to B is too slow.
Any help would be appreciated
After few hours of debugging i figured out the problem: in source code for unknowing reason author passed constant called MOUSE_HUMAN to variable named gravity when caling his function _humanWindMouse(), this looks like an error to me. Thats why I decided to fix this in my code, and throw out one argument of the function and a few lines of code (and that was wrong move). After re-adding needed code my function working, as I expected.
So, here's the working code:
# function HumanWindMouse by BenLand100 & Flight,
# python implementation by Nokse
def humanWindMouse(xs, ys, xe, ye, gravity, wind, targetArea):
veloX = veloY = windX=windY=veloMag=dist=randomDist=lastDist=D=0
lastX=lastY=MSP=W=TDist=0
mouseSpeed = 20
MSP = mouseSpeed
sqrt2 = sqrt(2)
sqrt3 = sqrt(3)
sqrt5 = sqrt(5)
TDist = distance(myround(xs), myround(ys), myround(xe), myround(ye))
t = time.time() + 10000
while True:
if time.time() > t:
break
dist = hypot(xs - xe, ys - ye)
wind = min(wind, dist)
if dist < 1:
dist = 1
D = (myround((myround(TDist)*0.3))/7)
if D > 25:
D = 25
if D < 5:
D = 5
rCnc = myrandom(6)
if rCnc == 1:
D = random.randint(2,3)
if D <= myround(dist):
maxStep = D
else:
maxStep = myround(dist)
if dist >= targetArea:
windX = windX / sqrt3 + (myrandom(myround(wind) * 2 + 1) - wind) / sqrt5
windY = windY / sqrt3 + (myrandom(myround(wind) * 2 + 1) - wind) / sqrt5
else:
windX = windX / sqrt2
windY = windY / sqrt2
veloX = veloX + windX
veloY = veloY + windY
veloX = veloX + gravity * (xe - xs) / dist
veloY = veloY + gravity * (ye - ys) / dist
if hypot(veloX, veloY) > maxStep:
halfSteps = int(myround(maxStep) // 2)
if halfSteps == 0:
halfSteps = 1
randomDist = maxStep / 2.0 + myrandom(halfSteps)
veloMag = sqrt(veloX * veloX + veloY * veloY)
veloX = (veloX / veloMag) * randomDist
veloY = (veloY / veloMag) * randomDist
lastX = myround(xs)
lastY = myround(ys)
xs = xs + veloX
ys = ys + veloY
if lastX <> myround(xs) or lastY <> myround(ys):
MMouseMove(myround(xs), myround(ys))
W = (myrandom((myround(100/MSP)))*6)
if W < 5:
W = 5
W = myround(W*0.9)
sleep(W/1000.0)
lastdist = dist
#condition for exiting while loop
if hypot(xs - xe, ys - ye) < 1:
break
if myround(xe) <> myround(xs) or myround(ye) <> myround(ys):
MMouseMove(myround(xe), myround(ye))
mouseSpeed = MSP
return;
I tested it with different parameters, and choose this one:
humanWindMouse(xs, ys, x, y, 9, 10.0/randSpeed, 10.0*randSpeed)
but I recommend to play with parameters first, to understand, how do they affect the behavior of the mouse.
How to calc randSpeed, what should be imported, and sub-functions, such as myround(), could be found at my first post.
Hope, this code will help somebody someday)

Finding intersection points of line and circle

Im trying to understand what this function does. It was given by my teacher and I just cant understands, whats logic behind the formulas finding x, and y coordinates. From my math class I know I my formulas for finding interception but its confusing translated in code. So I have some problems how they defined the formulas for a,b,c and for finding the coordinates x and y.
void Intersection::getIntersectionPoints(const Arc& arc, const Line& line) {
double a, b, c, mu, det;
std::pair<double, double> xPoints;
std::pair<double, double> yPoints;
std::pair<double, double> zPoints;
//(m2+1)x2+2(mc−mq−p)x+(q2−r2+p2−2cq+c2)=0.
//a= m2;
//b= 2 * (mc - mq - p);
//c= q2−r2+p2−2cq+c2
a = pow((line.end().x - line.start().x), 2) + pow((line.end().y - line.start().y), 2) + pow((line.end().z - line.start().z), 2);
b = 2 * ((line.end().x - line.start().x)*(line.start().x - arc.center().x)
+ (line.end().y - line.start().y)*(line.start().y - arc.center().y)
+ (line.end().z - line.start().z)*(line.start().z - arc.center().z));
c = pow((arc.center().x), 2) + pow((arc.center().y), 2) +
pow((arc.center().z), 2) + pow((line.start().x), 2) +
pow((line.start().y), 2) + pow((line.start().z), 2) -
2 * (arc.center().x * line.start().x + arc.center().y * line.start().y +
arc.center().z * line.start().z) - pow((arc.radius()), 2);
det = pow(b, 2) - 4 * a * c;
/* Tangenta na kružnicu */
if (Math<double>::isEqual(det, 0.0, 0.00001)) {
if (!Math<double>::isEqual(a, 0.0, 0.00001))
mu = -b / (2 * a);
else
mu = 0.0;
// x = h + t * ( p − h )
xPoints.second = xPoints.first = line.start().x + mu * (line.end().x - line.start().x);
yPoints.second = yPoints.first = line.start().y + mu * (line.end().y - line.start().y);
zPoints.second = zPoints.first = line.start().z + mu * (line.end().z - line.start().z);
}
if (Math<double>::isGreater(det, 0.0, 0.00001)) {
// first intersection
mu = (-b - sqrt(pow(b, 2) - 4 * a * c)) / (2 * a);
xPoints.first = line.start().x + mu * (line.end().x - line.start().x);
yPoints.first = line.start().y + mu * (line.end().y - line.start().y);
zPoints.first = line.start().z + mu * (line.end().z - line.start().z);
// second intersection
mu = (-b + sqrt(pow(b, 2) - 4 * a * c)) / (2 * a);
xPoints.second = line.start().x + mu * (line.end().x - line.start().x);
yPoints.second = line.start().y + mu * (line.end().y - line.start().y);
zPoints.second = line.start().z + mu * (line.end().z - line.start().z);
}
Denoting the line's start point as A, end point as B, circle's center as C, circle's radius as r and the intersection point as P, then we can write P as
P=(1-t)*A + t*B = A+t*(B-A) (1)
Point P will also locate on the circle, therefore
|P-C|^2 = r^2 (2)
Plugging equation (1) into equation (2), you will get
|B-A|^2*t^2 + 2(B-A)\dot(A-C)*t +(|A-C|^2 - r^2) = 0 (3)
This is how you get the formula for a, b and c in the program you posted. After solving for t, you shall obtain the intersection point(s) from equation (1). Since equation (3) is quadratic, you might get 0, 1 or 2 values for t, which correspond to the geometric configurations where the line might not intersect the circle, be exactly tangent to the circle or pass thru the circle at two locations.

Vectors -> Perpendicular distance from vector to point in 2D space

I have a sprite that moves along a vector (-0.7,-0.3). I have another point whose coordinates I have - let's call them (xB|yB). Now, quite some time ago I learned to calculate the perpendicular distance from a vector to a point (first formula on this page http://en.wikipedia.org/wiki/Perpendicular_distance). However I tried it, and if I log it, it returns an unbelievably high value that is 100% false. So what do I do wrong ? Have a look at the image I provided.
incomingVector = (-0.7,-0.3) //this is the vector the sprite is moving along
bh.position is the point I want to calculate the distance to
Here is the code:
// first I am working out the c Value in the formula in the link given above
CGPoint pointFromVector = CGPointMake(bh.incomingVector.x*theSprite.position.x,bh.incomingVector.y*theSprite.position.y);
float result = pointFromVector.x + pointFromVector.y;
float result2 = (-1)*result;
//now I use the formula
float test = (bh.incomingVector.x * bh.position.x + bh.incomingVector.y * bh.position.y + result2)/sqrt(pow(bh.incomingVector.x, 2)+pow(bh.incomingVector.y, 2));
//the distance has to be positive, so I do the following
if(test < 0){
test *= (-1);
}
let us implement the formula again, according to the contents of your original link.
we have a vector for the line: V(a; b)
we have a point on the line (the centre of the sprite): P(x1, y1)
we have another point somewhere else: B(xB, yB)
for the testing here are two rows of random values:
a = -0.7; b = -0.3; x1 = 7; y1 = 7; xB = 5; yB = 5;
a = -0.7; b = -0.3; x1 = 7; y1 = 7; xB = 5.5; yB = 4;
the numerator is the following then: (it seems you are calculating the numerator an unknown way, I don't understand why you did it because this is the proper way to calculate the numerator for the linked formula, perhaps this is why you got totally wrong distances.)
float _numerator = abs((b * xB) - (a * yB) - (b * x1) + (a * y1));
// for the 1. test values: (-0.3 * 5) - (-0.7 * 5) - (-0.3 * 7) + (-0.7 * 7) = -1.5 + 3.5 + 2.1 - 4.9 = -0.8 => abs(-0.8) = 0.8
// for the 2. test values: (-0.3 * 5.5) - (-0.7 * 4) - (-0.3 * 7) + (-0.7 * 7) = -1.65 + 2.8 + 2.1 - 4.9 = -1.65 => abs(-1.65) = 1.65
the denominator is the following then:
float _denomimator = sqrt((a * a) + (b * b));
// for the 1. test values: (-0.7 * -0.7) + (-0.3 * -0.3) = 0.49 + 0.09 = 0.58 => sort(0.58) = 0.76
// for the 2. test values: (-0.7 * -0.7) + (-0.3 * -0.3) = 0.49 + 0.09 = 0.58 => sort(0.58) = 0.76
the distance is obvious now:
float _distance = _numerator / _denominator;
// for the 1. test values: 0.8 / 0.76 = 1.05
// for the 2. test values: 1.65 / 0.76 = 2.17
and these results (1.05 and 2.17) are the correct distances exactly for our random values, if you can draw the lines and the points on the paper you can measure the distance and you would get the same values, using standard ruler.