How to find all point around center point in 2D - geometry

I have center point x: 0 and y: 0.
How to get all points distance Up to 5?
My code is not perfect:
function getPoints(startX, startY, distance) {
var res = []
for (var i = 1; i < distance; i++) {
res.push({ x: startX + i, y: startY })
res.push({ x: startX - i, y: startY })
res.push({ x: startX, y: startY + i })
res.push({ x: startX, y: startY - i })
res.push({ x: startX + i, y: startY + i })
res.push({ x: startX - i, y: startY - i })
}
console.log(res)
console.log(res.length)
}
getPoints(0, 0, 3)

Pseudocode (R=5 for your case)
for dy = 0 to R
for dx = 0 to Floor(Sqrt(R*R - dy*dy))
// or dx = 0
// while dx*dx+dy*dy<=R*R do
put startX + dx, startY + dy
put startX - dx, startY + dy
put startX + dx, startY - dy
put startX - dx, startY - dy
//dx++
If you need square, code is very simple:
for y = centerY - size to centerY + size
for x = centerX - size to centerX + size
put x, y

Related

How to calculate coordinates of 6 point of intersection between a circle and a equilateral triangle?

I know of an equilateral triangle the center (cx,cy) and the radius (r) of a blue circle which circumscribed it.
If I draw a green circle of any radius (radius), assuming the circle is large enough to have this intersection, can I get the coordinates of the 6 intersection points (P1, P2, P3...)?
I'm looking for P5JS/processing but any other clue can help me...
Thank you in advance
Distance from the center to top point is r.
Distance from the center to the lowest triangle side is r/2 (median intersection point is center, they are divided in 1:2 ratio).
Horizontal distance from cx to p4 (and p5) is (Pythagoras' theorem)
dx = sqrt(radius^2 - r^2/4)
So coordinates of p4 and p5 are (relative to center)
p4x = dx
p4y = r/2
p5x = -dx
p5y = r/2
Other points might be calculated using rotation by 120 degrees
p2x = p4x*(-1/2) - p4y*(sqrt(3)/2)
p2y = p4x*(sqrt(3)/2) + p4y*(-1/2)
and so on.
And finally add cx,cy to get absolute coordinates
If you want to test... ;-)
function setup() {
createCanvas(500, 500);
const cx = width / 2;
const cy = height / 2;
const r = 250; // taille du triangle
const radius = 180; // externe
noFill();
strokeWeight(3);
stroke(0, 0, 0);
drawTriangle(cx, cy, r);
strokeWeight(1);
stroke(0, 0, 255);
circle(cx, cy, r * 2);
strokeWeight(2);
stroke(8, 115, 0);
circle(cx, cy, radius * 2);
noStroke();
fill(215, 0, 0);
// dx = sqrt(Math.pow(r / 2, 2) - Math.pow(r / 2, 2 / 4));
dx = sqrt(radius * radius - (r * r) / 4);
p4x = dx;
p4y = r / 2;
circle(cx + p4x, cy + p4y, 20);
text("p4", cx + p4x, cy + p4y + 30);
p5x = -dx;
p5y = r / 2;
circle(cx + p5x, cy + p5y, 20);
text("p5", cx + p5x - 10, cy + p5y + 30);
p6x = p4x * (-1 / 2) - p4y * (sqrt(3) / 2);
p6y = p4x * (sqrt(3) / 2) + p4y * (-1 / 2);
circle(cx + p6x, cy + p6y, 20);
text("p6", cx + p6x - 30, cy + p6y);
p2x = p6x * (-1 / 2) - p6y * (sqrt(3) / 2);
p2y = p6x * (sqrt(3) / 2) + p6y * (-1 / 2);
circle(cx + p2x, cy + p2y, 20);
text("p2", cx + p2x + 10, cy + p2y - 10);
p1x = p5x * (-1 / 2) - p5y * (sqrt(3) / 2);
p1y = p5x * (sqrt(3) / 2) + p5y * (-1 / 2);
circle(cx + p1x, cy + p1y, 20);
text("p1", cx + p1x - 20, cy + p1y - 10);
p3x = p1x * (-1 / 2) - p1y * (sqrt(3) / 2);
p3y = p1x * (sqrt(3) / 2) + p1y * (-1 / 2);
circle(cx + p3x, cy + p3y, 20);
text("p3", cx + p3x + 20, cy + p3y - 10);
noFill();
stroke(0, 255, 255);
triangle(cx + p2x, cx + p2y, cx + p4x, cx + p4y, cx + p6x, cx + p6y);
stroke(255, 0, 255);
// prettier-ignore
triangle(
cx + p1x, cx + p1y,
cx + p3x, cx + p3y,
cx + p5x, cx + p5y,
)
}
function drawTriangle(cx, cy, radius) {
noFill();
trianglePoints = [];
for (var i = 0; i < 3; i++) {
var x = cx + radius * cos((i * TWO_PI) / 3.0 - HALF_PI);
var y = cy + radius * sin((i * TWO_PI) / 3.0 - HALF_PI);
trianglePoints[i] = {
x,
y,
};
}
triangle(
trianglePoints[0].x,
trianglePoints[0].y,
trianglePoints[1].x,
trianglePoints[1].y,
trianglePoints[2].x,
trianglePoints[2].y
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.min.js"></script>

Is there a better way to generate points on a circle than trying out points in the equation x^2 + y^2 = r^2?

I have seen many apps which draw circles e.g pygame for python, p5.js for javascript. But I cannot find a method to find out points on a circle efficiently. My current solution to the problem involves trying out all the numbers in the square in which the circle can be inscribed.
This can't be the most efficient method to do it. What is the method used at the industry level? Does it involve optimization or is it a whole new method?
A Midpoint Circle Algorithm could be used.
And an implementation e.g. in C from rosettacode.org:
#define plot(x, y) put_pixel_clip(img, x, y, r, g, b)
void raster_circle(
image img,
unsigned int x0,
unsigned int y0,
unsigned int radius,
color_component r,
color_component g,
color_component b )
{
int f = 1 - radius;
int ddF_x = 0;
int ddF_y = -2 * radius;
int x = 0;
int y = radius;
plot(x0, y0 + radius);
plot(x0, y0 - radius);
plot(x0 + radius, y0);
plot(x0 - radius, y0);
while(x < y)
{
if(f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x + 1;
plot(x0 + x, y0 + y);
plot(x0 - x, y0 + y);
plot(x0 + x, y0 - y);
plot(x0 - x, y0 - y);
plot(x0 + y, y0 + x);
plot(x0 - y, y0 + x);
plot(x0 + y, y0 - x);
plot(x0 - y, y0 - x);
}
}

Geometry Arc Algorithm

I searched all internet and didn't find any pseudo code that solved this problem,
I want to find an Arc between two points, A and B, using 5 arguments:
Start Point
End Point
Radius (Don't know if this is needed)
Angle
Quality
Example:
StartPoint = The green point on the left is the Start Point set on the arguments
EndPoint = The green point on the right is the End Point set on the arguments
Angle = Angle of the Arc(Semi Circle)
Quality = How many red circles to create
I would like to have a pseudo code to solve this problem
Thanks in advance :D
Let start point is P0, end point P1, angle Fi. R is not needed
At first find arc center. Get middle of P0-P1 segment.
M = (P0 + P1) / 2
// M.x = (P0.x + P1.x) / 2 , same for y
And direction vector
D = (P1 - P0) / 2
Get length of D
lenD = Math.Hypot(D.x, D.y) //Vector.Length, sqrt of sum of squares
Get unit vector
uD = D / lenD
Get (left) perpendicular vector
(P.x, P.y) = (-uD.y, ud.x)
Now circle center
if F = Pi then
C.x = M.x
C.y = M.y
else
C.x = M.x + P.x * Len / Tan(Fi/2)
C.y = M.y + P.y * Len / Tan(Fi/2)
Vector from center to start point:
CP0.x = P0.x - C.x
CP0.y = P0.y - C.y
Then you can calculate coordinates of N intermediate points at the arc using rotation of vector CP0 around center point
an = i * Fi / (NSeg + 1);
X[i] = C.x + CP0.x * Cos(an) - CP0.y * Sin(an)
Y[i] = C.y + CP0.x * Sin(an) + CP0.y * Cos(an)
Working Delphi code
procedure ArcByStartEndAngle(P0, P1: TPoint; Angle: Double; NSeg: Integer);
var
i: Integer;
len, dx, dy, mx, my, px, py, t, cx, cy, p0x, p0y, an: Double;
xx, yy: Integer;
begin
mx := (P0.x + P1.x) / 2;
my := (P0.y + P1.y) / 2;
dx := (P1.x - P0.x) / 2;
dy := (P1.y - P0.y) / 2;
len := Math.Hypot(dx, dy);
px := -dy / len;
py := dx / len;
if Angle = Pi then
t := 0
else
t := len / Math.Tan(Angle / 2);
cx := mx + px * t;
cy := my + py * t;
p0x := P0.x - cx;
p0y := P0.y - cy;
for i := 0 to NSeg + 1 do begin
an := i * Angle / (NSeg + 1);
xx := Round(cx + p0x * Cos(an) - p0y * Sin(an));
yy := Round(cy + p0x * Sin(an) + p0y * Cos(an));
Canvas.Ellipse(xx - 3, yy - 3, xx + 4, yy + 4);
end;
end;
Result for (Point(100, 0), Point(0, 100), Pi / 2, 8 (Y-axis down at the picture)

Processing: Distance of intersection between line and circle

Now, I know similar questions have been asked. But none of the answers has helped me to find the result I need.
Following situation:
We have a line with a point-of-origin (PO), given as lx, ly. We also have an angle for the line in that it exits PO, where 0° means horizontally to the right, positive degrees mean clockwise. The angle is in [0;360[. Additionally we have the length of the line, since it is not infinitely long, as len.
There is also a circle with the given center-point (CP), given as cx, cy. The radius is given as cr.
I now need a function that takes these numbers as parameters and returns the distance of the closest intersection between line and circle to the PO, or -1 if no intersection occures.
My current approach is a follows:
float getDistance(float lx, float ly, float angle, float len, float cx, float cy, float cr) {
float nlx = lx - cx;
float nly = ly - cy;
float m = tan(angle);
float b = (-lx) * m;
// a = m^2 + 1
// b = 2 * m * b
// c = b^2 - cr^2
float[] x_12 = quadraticFormula(sq(m) + 1, 2*m*b, sq(b) - sq(cr));
// if no intersections
if (Float.isNaN(x_12[0]) && Float.isNaN(x_12[1]))
return -1;
float distance;
if (Float.isNaN(x_12[0])) {
distance = (x_12[1] - nlx) / cos(angle);
} else {
distance = (x_12[0] - nlx) / cos(angle);
}
if (distance <= len) {
return distance;
}
return -1;
}
// solves for x
float[] quadraticFormula(float a, float b, float c) {
float[] results = new float[2];
results[0] = (-b + sqrt(sq(b) - 4 * a * c)) / (2*a);
results[1] = (-b - sqrt(sq(b) - 4 * a * c)) / (2*a);
return results;
}
But the result is not as wished. Sometimes I do get a distance returned, but that is rarely correct, there often isn't even an intersection occuring. Most of the time no intersection is returned though, although there should be one.
Any help would be much appreciated.
EDIT:
I managed to find the solution thanks to MBo's answer. Here is the content of my finished getDistance(...)-function - maybe somebody can be helped by it:
float nlx = lx - cx;
float nly = ly - cy;
float dx = cos(angle);
float dy = sin(angle);
float[] results = quadraticFormula(1, 2*(nlx*dx + nly*dy), sq(nlx)+sq(nly)-sq(cr));
float dist = -1;
if (results[0] >= 0 && results[0] <= len)
dist = results[0];
if (results[1] >= 0 && results[1] <= len && results[1] < results[0])
dist = results[1];
return dist;
Using your nlx, nly, we can build parametric equation of line segment
dx = Cos(angle)
dy = Sin(Angle)
x = nlx + t * dx
y = nly + t * dy
Condition of intersection with circumference:
(nlx + t * dx)^2 + (nly + t * dy)^2 = cr^2
t^2 * (dx^2 + dy^2) + t * (2*nlx*dx + 2*nly*dy) + nlx^2+nly^2-cr^2 = 0
so we have quadratic equation for unknown parameter t with
a = 1
b = 2*(nlx*dx + nly*dy)
c = nlx^2+nly^2-cr^2
solve quadratic equation, find whether t lies in range 0..len.
// https://openprocessing.org/sketch/8009#
// by https://openprocessing.org/user/54?view=sketches
float circleX = 200;
float circleY = 200;
float circleRadius = 100;
float lineX1 = 350;
float lineY1 = 350;
float lineX2, lineY2;
void setup() {
size(400, 400);
ellipseMode(RADIUS);
smooth();
}
void draw() {
background(204);
lineX2 = mouseX;
lineY2 = mouseY;
if (circleLineIntersect(lineX1, lineY1, lineX2, lineY2, circleX, circleY, circleRadius) == true) {
noFill();
}
else {
fill(255);
}
ellipse(circleX, circleY, circleRadius, circleRadius);
line(lineX1, lineY1, lineX2, lineY2);
}
// Code adapted from Paul Bourke:
// http://local.wasp.uwa.edu.au/~pbourke/geometry/sphereline/raysphere.c
boolean circleLineIntersect(float x1, float y1, float x2, float y2, float cx, float cy, float cr ) {
float dx = x2 - x1;
float dy = y2 - y1;
float a = dx * dx + dy * dy;
float b = 2 * (dx * (x1 - cx) + dy * (y1 - cy));
float c = cx * cx + cy * cy;
c += x1 * x1 + y1 * y1;
c -= 2 * (cx * x1 + cy * y1);
c -= cr * cr;
float bb4ac = b * b - 4 * a * c;
//println(bb4ac);
if (bb4ac < 0) { // Not intersecting
return false;
}
else {
float mu = (-b + sqrt( b*b - 4*a*c )) / (2*a);
float ix1 = x1 + mu*(dx);
float iy1 = y1 + mu*(dy);
mu = (-b - sqrt(b*b - 4*a*c )) / (2*a);
float ix2 = x1 + mu*(dx);
float iy2 = y1 + mu*(dy);
// The intersection points
ellipse(ix1, iy1, 10, 10);
ellipse(ix2, iy2, 10, 10);
float testX;
float testY;
// Figure out which point is closer to the circle
if (dist(x1, y1, cx, cy) < dist(x2, y2, cx, cy)) {
testX = x2;
testY = y2;
} else {
testX = x1;
testY = y1;
}
if (dist(testX, testY, ix1, iy1) < dist(x1, y1, x2, y2) || dist(testX, testY, ix2, iy2) < dist(x1, y1, x2, y2)) {
return true;
} else {
return false;
}
}
}

How to calculate width, height and position of bezier curve

I have a bezier curve defined by start point, end point and 2 control points (parameters of this: http://www.w3schools.com/tags/canvas_beziercurveto.asp).
First, I need to calculate width and height of this curve. If I make rectangle around a curve, its width and height is what I need.
Then I need to start point (x,y of left top corner) of this rectangle.
How can I calculate that ? Thanks.
For true bounds, you need to compute the extremities of the curve's component functions, then plug those into the bezier function for the (x,y) coordinates for each extremity. I cover this over at http://pomax.github.io/bezierinfo/#extremities, which also explains how to do most of the steps required to get there in the text leading up to the extremities section. paragraphs 11 and 12/13 then cover bounding boxes (plain, which you're probably interested in, and tight, respectively)
I found approximate solution in some other topic (I don't remember which one) but here is simple JS function to calculate it:
function getCurveBoundary(ax, ay, bx, by, cx, cy, dx, dy) {
var tobx = bx - ax;
var toby = by - ay;
var tocx = cx - bx;
var tocy = cy - by;
var todx = dx - cx;
var tody = dy - cy;
var step = 1 / 40; // precission
var d, px, py, qx, qy, rx, ry, tx, ty, sx, sy, x, y, i, minx, miny, maxx, maxy;
function min(num1, num2) {
if (num1 > num2)
return num2;
if (num1 < num2)
return num1;
return num1;
}
function max(num1, num2) {
if (num1 > num2)
return num1;
if (num1 < num2)
return num2;
return num1;
}
for (var i = 0; i < 41; i++)
{
d = i * step;
px = ax + d * tobx;
py = ay + d * toby;
qx = bx + d * tocx;
qy = by + d * tocy;
rx = cx + d * todx;
ry = cy + d * tody;
toqx = qx - px;
toqy = qy - py;
torx = rx - qx;
tory = ry - qy;
sx = px + d * toqx;
sy = py + d * toqy;
tx = qx + d * torx;
ty = qy + d * tory;
totx = tx - sx;
toty = ty - sy;
x = sx + d * totx;
y = sy + d * toty;
if (i == 0)
{
minx = x;
miny = y;
maxx = x;
maxy = y;
}
else
{
minx = min(minx, x);
miny = min(miny, y);
maxx = max(maxx, x);
maxy = max(maxy, y);
}
}
return {x: Math.round(minx), y: Math.round(miny), width: Math.round(maxx - minx), height: Math.round(maxy - miny)};
}
If you're looking for an approximate solution, it's pretty easy to compute a solution that's always big enough to cover the curve, but might be too big.
Beziers satisfy the 'convex hull property' which means that you can take a bounding box of your control points and that will bound the curve itself.
If you're looking for something more accurate, then the simplest way is to evaluate a bunch of different points on the curve and take the bounding box of those points on the curve. You can vary the number of points you test in order to change the quality/speed tradeoff.
If you're looking for something that directly computes the exact answer then what you need is a root finder to look for extrema of the functions x(t) and y(t).

Resources