Gnu Octave Quadratic Equation Graphic - gnuplot

I lost two days of trying to do this but with no result. How can I plot the quadratic equation's parabola and roots. Something like this. I just need to be able to see the parabola and that it crosses the abscissa at the write coordinates.
Here is what I have:
x = linspace(-50,50);
y = 1.*x.*x - 8.*x + 15;
plot(x,y)
hold on;
grid()
rts = roots([1,-8,15]);
plot(rts, zeros(size(rts)), 'o', "color", "r")
And the result is:
As you can see, the top of the parabola at 0 ordinate, instead of under it. I will appreciate your help!

Using a smaller linspace range works fine for me:
x = linspace(1,6);
y = 1.*x.*x - 8.*x + 15;
plot(x,y)
hold on;
grid()
rts = roots([1,-8,15]);
plot(rts, zeros(size(rts)), 'o', "color", "r")

Christoph is right the plot could be misleading because a great linspace can flatten the part of the curve below the abscissa, and if you don't think and you make some error calculating the vertex, as I've done you are fried! This is another solution, I hope this one is right!
ezplot(#(x,y) x.^2 -x.*8 -y.+ 15)
hold on
grid on
rts = roots([1,-8,15]);
plot(rts,zeros(size(rts)),'o',"color","r");
line(xlim,[0 0], 'linestyle', '--')

Related

Is there a logic error with my implementation of odeint?

I am getting the wrong solution and am unsure if odeint is the correct tool for solving this system of ODEs.
I am trying to model a simple first order chemical reaction by solving a system of ODEs. From a logic standpoint my functions are correct and I can solve this problem in MATLAB with little issue. I would like to also be able to do this work in python as well. I think odeint is the tool for the job but I could be wrong. My solution should not converge at independent variable = 10 every time but it always does regardless of inputs.
from matplotlib.pyplot import (plot,grid,xlabel,ylabel,show,legend)
import numpy as np
from scipy.integrate import odeint
wght= np.linspace(0,20)
# reaction is A -> B
def PBR(fun,W):
X,y = fun
P_0=20;#%bar
v_0=5; #%m^3/min
y_A0=1; #unitless
k=.005; #m^3/kg/min
alpha=0.1; #1/kg
epi=.13; #unitless
R=8.314; #J/mol/K
F_A0= .5 ;#mol/min
ra = -k *y*(1-X)/(1+epi*X)
dX = (-ra)/F_A0
dy = -alpha*(1+epi*X)/(2*y)
return [dX,dy]
X0 = 0.0
y0 = 1.0
sol = odeint(PBR, [X0, y0],wght)
plot(wght, sol[:, 0], 'b', label='X')
plot(wght, sol[:, 1], 'g', label='y')
legend(loc='best')
xlabel('W')
grid()
show()
print(sol)
Output graph
Your graphic is not reproducible, in python 3.7, scipy 1.4.1, I get a divergence to practically infinity at around 12.5, and after cleaning the work space, both graphs moving to zero after time 10.
The problem is your division by 2*y in the second equation. In effect that means that y is the square root of some other function, and that type of function behaves badly numerically at small values as the tangent becomes vertical, changing to zero shortly after.
However, one can desingularize the division in a simple way
dy = -alpha*(1+epi*X)*y/(1e-10+2*y*y)
or in a more complicated way that leaves the solution far away from zero really unchanged
dy = -alpha*(1+epi*X)*y/(y*y+max(1e-12,y*y))
resulting in the graph
If that is still not the expected behavior, then something else is different in your ODE system relative to the Matlab version.
That the singular point is at about w=10 depends almost completely on alpha=0.1. As epi is small and X is initially small, the second equation is close to
d(y^2)/dW = -alpha ==> y^2 = 1 - alpha*W
and this hits zero at about W=10 where the solution would have to end as the square of y can not take negative values.

making a function that translates a point around another point

given an array of points my program should in theory, Find the two furthest points from each other. Then calculate the angle that those two points make with the x axis. Then in rotate all the points in the array around the averaged center of all the points by that angle. For some reason my translation function to rotate all the points around the center is not working it is giving me unexpected values. I am fairly sure the math I am using to do this is accurate since I tested the formula I am using using wolfram alpha and plotted the points on desmos. I am not sure what's wrong with my code because it keeps giving me unexpected output. Any help would greatly be appreciated.
This is the code to translate the array:
def translation(array,centerArray):
array1=array
maxDistance=0
point1=[]
point2=[]
global angle
for i in range(len(array1)):
for idx in range(len(array1)):
if(maxDistance<math.sqrt(((array1[i][0]-array1[idx][0])**2)+((array1[i][1]-array1[idx][1])**2)+((array1[i][2]-array1[idx][2])**2))):
maxDistance=math.sqrt(((array1[i][0]-array1[idx][0])**2)+((array1[i][1]-array1[idx][1])**2)+((array1[i][2]-array1[idx][2])**2))
point1 = array1[i]
point2 = array1[idx]
angle=math.atan2(point1[1]-point2[1],point1[0]-point2[0]) #gets the angle between two furthest points and xaxis
for i in range(len(array1)): #this is the problem here
array1[i][0]=((array[i][0]-centerArray[0])*math.cos(angle)-(array[i][1]-centerArray[1])*math.sin(angle))+centerArray[0] #rotate x cordiate around center of all points
array1[i][1]=((array[i][1]-centerArray[1])*math.cos(angle)+(array[i][0]-centerArray[0])*math.sin(angle))+centerArray[1] #rotate y cordiate around center of all points
return array1
This is the code I am using to test it. tortose is what I set turtle graphics name as
tortose.color("violet")
testarray=[[200,400,9],[200,-100,9]] #array of 2 3d points but don't worry about z axis it will not be used for in function translation
print("testsarray",testarray)
for i in range(len(testarray)): #graph points in testarray
tortose.setposition(testarray[i][0],testarray[i][1])
tortose.dot()
testcenter=findCenter(testarray) # array of 1 point in the center of all the points format center=[x,y,z] but again don't worry about z
print("center",testcenter)
translatedTest=translation(testarray,testcenter) # array of points after they have been translated same format and size of testarray
print("translatedarray",translatedTest) #should give the output [[-50,150,9]] as first point but instead give output of [-50,-99.999999997,9] not sure why
tortose.color("green")
for i in range(len(testarray)): #graphs rotated points
tortose.setposition(translatedTest[i][0],translatedTest[i][1])
tortose.dot()
print(angle*180/3.14) #checks to make sure angle is 90 degrees because it should be in this case this is working fine
tortose.color("red")
tortose.setposition(testcenter[0],testcenter[1])
tortose.dot()
find center code finds the center of all points in array don't worry about z axis since it is not used in translation:
def findCenter(array):
sumX = 0
sumY = 0
sumZ = 0
for i in range(len(array)):
sumX += array[i][0]
sumY += array[i][1]
sumZ += array[i][2]
centerX= sumX/len(array)
centerY= sumY/len(array)
centerZ= sumZ/len(array)
#print(centerX)
#print(centerY)
#print(centerZ)
centerArray=[centerX,centerY,centerZ]
return centerArray
import math
import turtle
tortose = turtle.Turtle()
tortose.penup()
my expected output should be a point at (-50,150) but it is giving me a point at (-50,-99.99999999999997)
This is a common mistake when doing in-place rotations:
array1[i][0]= ...
array1[i][1]= ... array[i][0] ...
First you update array1[i][0]. Then you update array1[i][1], but you use the new value when you should use the old value. Instead, temporarily store the old value:
x = array1[i][0]
array1[i][0]=((array[i][0]-centerArray[0])*math.cos(angle)-(array[i][1]-centerArray[1])*math.sin(angle))+centerArray[0] #rotate x cordiate around center of all points
array1[i][1]=((array[i][1]-centerArray[1])*math.cos(angle)+(x-centerArray[0])*math.sin(angle))+centerArray[1] #rotate y cordiate around center of all points

How to get a point on an ellipse's outline given an angle?

So, I have ellipses given - they are defined by their midpoint, an horizontal radius(rh) and an vertical radius(rv). I'm drawing them using sin/cos and the result looks fairly good to me(just making sure this isn't an error source).
Now say I have an angle(or a direction vector) given and I want to have the point on the ellipse's outline with that angle/direction. My intuitive approach was to simply use the direction vector, normalise it and multiply its x-component with rh, its y-component with rv. Now both my written program AND all the calculations I did on a paper give me not the point I want but another one, though it's still on the ellipse's outline. However, this method works just fine if the direction is one of (1,0), (0, 1), (-1, 0), (0, -1), (so it works for 0°, 90°, 180°, 270°).
Although there is a farily big amount of data about ellipses themselves on the internet, I couldn't find any information about my particular problem - and I couldn't come up with any better solution than the above one.
So, any idea how to achieve this?
If I understand what you are asking then I think that what you need is polar form of an ellipse where the angle is measured from the ellipse centre. Using this form of the ellipse, you will be able to evaulate your elliptic radius value for a given choice of theta and then plot your point.
If you take a look at this gif image you will see why using the parametric angle give you the correct result only at theta = 90, 180, 270 and 360 degrees http://en.wikipedia.org/wiki/File:Parametric_ellipse.gif . Use the polar form for an ellipse and you should get the points that you want.
You are correct - the parametric angle is not the same as the angle between the desired point and the X axis. However, their tangents are proportional (with a factor of rh/rv) so you can use this approach:
Get the tangent of the desired angle
Multiply this tangent by rh/rv
Use trigonometric identities to compute the sine and cosine from the tangent
Scale/position the point according to the parameters (midpoint, rh, rv)
In Python:
from math import copysign, cos, sin, sqrt
class Ellipse:
def __init__(self, mx, my, rh, rv):
self.mx = mx
self.my = my
self.rh = rh
self.rv = rv
def pointFromAngle(self, a):
c = cos(a)
s = sin(a)
ta = s / c ## tan(a)
tt = ta * self.rh / self.rv ## tan(t)
d = 1. / sqrt(1. + tt * tt)
x = self.mx + copysign(self.rh * d, c)
y = self.my + copysign(self.rv * tt * d, s)
return x, y

Find the corners of a deformed rectangle

I am trying to make a program that automatically corrects the perspective of a rectangle. I have managed to get the silhouette of the rectangle, and have the code to correct the perspective, but I can't find the corners. The biggest problem is that, because it has been deformed, I can't use the following "code":
c1 = min(x), min(y)
c2 = max(x), min(y)
c3 = min(x), max(y)
c4 = max(x), max(y)
This wouldn't work with this situation (X represents a corner):
X0000000000X
.00000000000
..X000000000
.....0000000
........0000
...........X
Does anyone know how to do this?
Farthest point from the center will give you one corner.
Farthest point from the first corner will give you another corner, which may be either adjacent or opposite to the first.
Farthest point from the line between those two corners (a bit more math intensitive) will give you a third corner. I'd use distance from center as a tie breaker.
For finding the 4th corner, it'll be the point outside the triangle formed by the first 3 corners you found, farthest from the nearest line between those corners.
This is a very time consuming way to do it, and I've never tried it, but it ought to work.
You could try to use a scanline algorithm - For every line of the polygon (so y = min(y)..max(y)), get l = min(x) and r = max(x). Calculate the left/right slope (deltax) and compare it with the slope the line before. If it changed (use some tolerance here), you are at a corner of the rectangle (or close to it). That won't work for all cases, as the slope can't be that exact because of low resolution, but for large rectangles and slopes not too similar, this should work.
At least, it works well for your example:
X0000000000X l = 0, r = 11
.00000000000 l = 1, r = 11, deltaxl = 1, deltaxr = 0
..X000000000 l = 2, r = 11, deltaxl = 1, deltaxr = 0
.....0000000 l = 5, r = 11, deltaxl = 3, deltaxr = 0
........0000 l = 8, r = 11, deltaxl = 3, deltaxr = 0
...........X l = 11, r = 11, deltaxl = 3, deltaxr = 0
You start with the top of the rectangle where you get two different values for l and r, so you already have two of the corners. On the left side, for the first three lines you'll get deltax = 1, but after it, you'll get deltax = 3, so there is a corner at (3, 3). On the right side, nothing changes, deltax = 0, so you only get the point at the end.
Note that you're "collecting" corners here, so if you don't have 4 corners at the end, the slopes were too similar (or you have a picture of a triangle) and you can switch to a different (more exact) algorithm or just give an error. The same if you have more than 4 corners or some other strange things like holes in the rectangle. It seems some kind of image detection is involved, so these cases can occur, right?
There are cases in which a simple deltax = (x - lastx) won't work good, see this example for the left side of a rectangle:
xxxxxx
xxxxx deltax = 1 dy/dx = 1/1 = 1
xxxxx deltax = 0 dy/dx = 2/1 = 2
xxxx deltax = 1 dy/dx = 3/2 = 1.5
xxxx deltax = 0 dy/dx = 4/2 = 2
xxx deltax = 1 dy/dx = 5/3 = 1.66
Sometimes deltax is 0, sometimes is 1. It's better to use the slope of the line from the actual point to the top left/right point (deltay / deltax). Using it, you'll still have to stick with a tolerance, but your values will get more exact with each new line.
You could use a hough transform to find the 4 most prominent lines in the masked image. These lines will be the sides of the quadrangle.
The lines will intersect in up to 6 points, which are the 4 corners and the 2 perspective vanishing points.
These are easy to distinguish: pick any point inside the quadrangle, and check if the line from this point to each of the 6 intersection points intersects any of the lines. If not, then that intersection point is a corner.
This has the advantage that it works well even for noisy or partially obstructed images, or if your segmentation is not exact.
en.wikipedia.org/wiki/Hough_transform
Example CImg Code
I would be very interested in your results. I have been thinking about writing something like this myself, to correct photos of paper sheets taken at an angle. I am currently struggling to think of a way to correct the perspective if the 4 points are known
p.s.
Also check out
Zhengyou Zhang , Li-Wei He, "Whiteboard scanning and image enhancement"
http://research.microsoft.com/en-us/um/people/zhang/papers/tr03-39.pdf
for a more advanced solution for quadrangle detection
I have asked a related question, which tries to solve the perspective transform:
proportions of a perspective-deformed rectangle
This looks like a convex hull problem.
http://en.wikipedia.org/wiki/Convex_hull
Your problem is simpler but the same solution should work.

Given a set of points, how do I approximate the major axis of its shape?

Given a "shape" drawn by the user, I would like to "normalize" it so they all have similar size and orientation. What we have is a set of points. I can approximate the size using bounding box or circle, but the orientation is a bit more tricky.
The right way to do it, I think, is to calculate the majoraxis of its bounding ellipse. To do that you need to calculate the eigenvector of the covariance matrix. Doing so likely will be way too complicated for my need, since I am looking for some good-enough estimate. Picking min, max, and 20 random points could be some starter. Is there an easy way to approximate this?
Edit:
I found Power method to iteratively approximate eigenvector. Wikipedia article.
So far I am liking David's answer.
You'd be calculating the eigenvectors of a 2x2 matrix, which can be done with a few simple formulas, so it's not that complicated. In pseudocode:
// sums are over all points
b = -(sum(x * x) - sum(y * y)) / (2 * sum(x * y))
evec1_x = b + sqrt(b ** 2 + 1)
evec1_y = 1
evec2_x = b - sqrt(b ** 2 + 1)
evec2_y = 1
You could even do this by summing over only some of the points to get an estimate, if you expect that your chosen subset of points would be representative of the full set.
Edit: I think x and y must be translated to zero-mean, i.e. subtract mean from all x, y first (eed3si9n).
Here's a thought... What if you performed a linear regression on the points and used the slope of the resulting line? If not all of the points, at least a sample of them.
The r^2 value would also give you information about the general shape. The closer to 0, the more circular/uniform the shape is (circle/square). The closer to 1, the more stretched out the shape is (oval/rectangle).
The ultimate solution to this problem is running PCA
I wish I could find a nice little implementation for you to refer to...
Here you go! (assuming x is a nx2 vector)
def majAxis(x):
e,v = np.linalg.eig(np.cov(x.T)); return v[:,np.argmax(e)]

Resources