Related
I need to loop through a array in circle in arc shape with a small radius (like draw a circle pixel by pixel), but all algorithm i tried, checks duplicate indexes of array (it's got the same x and y several times).
I have a radius of 3, with a circle form of 28 elements (not filled), but the algorithm iterate 360 times. I can check if x or y change before i do something, but it's lame.
My code now:
for (int radius = 1; radius < 6; radius++)
{
for (double i = 0; i < 360; i += 1)
{
double angle = i * System.Math.PI / 180;
int x = (int)(radius * System.Math.Cos(angle)) + centerX;
int y = (int)(radius * System.Math.Sin(angle)) + centerY;
// do something
// if (array[x, y]) ....
}
}
PS: I can't use midpoint circle, because i need to increment radius starting from 2 until 6, and not every index is obtained, because his circle it's not real (according trigonometry)
EDIT:
What i really need, is scan a full circle edge by edge, starting by center.
360 steps (it's get all coordinates):
Full scan
for (int radius = 2; radius <= 7; radius++)
{
for (double i = 0; i <= 360; i += 1)
{
double angle = i * System.Math.PI / 180;
int x = (int)(radius * System.Math.Cos(angle));
int y = (int)(radius * System.Math.Sin(angle));
print(x, y, "X");
}
}
Using Midpoint Circle or other algorithm skipping steps (missing coordinates):
Midpoint Circle Algorithm
for (int radius = 2; radius <= 7; radius++)
{
int x = radius;
int y = 0;
int err = 0;
while (x >= y)
{
print(x, y, "X");
print(y, x, "X");
print(-y, x, "X");
print(-y, x, "X");
print(-x, y, "X");
print(-x, -y, "X");
print(-y, -x, "X");
print(y, -x, "X");
print(x, -y, "X");
y += 1;
err += 1 + 2 * y;
if (2 * (err - x) + 1 > 0)
{
x -= 1;
err += 1 - 2 * x;
}
}
}
There are two algorithmic ideas in play here: one is rasterizing a circle. The OP code presents a couple opportunities for improvement on that front: (a) one needn't sample the entire 360 degree circle, realizing that a circle is symmetric across both axes. (x,y) can be reflected in the other three quadrants as (-x,y), (-x,-y), and (x,-y). (b) the step on the loop should be related to the curvature. A simple heuristic is to use the radius as the step. So...
let step = MIN(radius, 90)
for (double i=0; i<90; i += step) {
add (x,y) to results
reflect into quadrants 2,3,4 and add to results
}
With these couple improvements, you may no longer care about duplicate samples being generated. If you still do, then the second idea, independent of the circle, is how to hash a pair of ints. There's a good article about that here: Mapping two integers to one, in a unique and deterministic way.
In a nutshell, we compute an int from our x,y pair that's guaranteed to map uniquely, and then check that for duplicates...
cantor(x, y) = 1/2(x + y)(x + y + 1) + y
This works only for positive values of x,y, which is just what you need since we're only computing (and then reflecting) in the first quadrant. For each pair, check that they are unique
let s = an empty set
int step = MIN(radius, 90)
for (double i=0; i<90; i += step) {
generate (x,y)
let c = cantor(x,y)
if (not(s contains c)) {
add (x,y) to results
reflect into quadrants 2,3,4 and add to results
add c to s
}
}
Got it!
It's not beautiful, but work for me.
int maxRadius = 7;
for (int radius = 1; radius <= maxRadius; radius++)
{
x = position.X - radius;
y = position.Y - radius;
x2 = position.X + radius;
y2 = position.Y + radius;
for (int i = 0; i <= radius * 2; i++)
{
if (InCircle(position.X, position.Y, x + i, y, maxRadius)) // Top X
myArray[position, x + i, y]; // check array
if (InCircle(position.X, position.Y, x + i, y2, maxRadius)) // Bottom X
myArray[position, x + i, y2]; // check array
if (i > 0 && i < radius * 2)
{
if (InCircle(position.X, position.Y, x, y + i, maxRadius)) // Left Y
myArray[position, x, y + i]; // check array
if (InCircle(position.X, position.Y, x2, y + i, maxRadius)) // Right Y
myArray[position, x2, y + i]; // check array
}
}
}
public static bool InCircle(int originX, int originY, int x, int y, int radius)
{
int dx = Math.Abs(x - originX);
if (dx > radius) return false;
int dy = Math.Abs(y - originY);
if (dy > radius) return false;
if (dx + dy <= radius) return true;
return (dx * dx + dy * dy <= radius * radius);
}
I'm looking at a paper named "Shape Based Image Retrieval Using Generic Fourier Descriptors", but only have rudimentary knowledge of Fourier Descriptors. I am attempting to implement the algorithm on page 12 of the paper, and have some results which I can't really make too much sense out of.
If I create an small image, take calculate the FD for the image, and compare the FD to the same image which has been translated by a single pixel in the x and y directions, the descriptor is completely different, except for the first entry - which is exactly the same. Firstly, a question is, is should these descriptors be exactly the same (as the descriptor is apparently scale, rotation, and translation invariant) between the two images?
Secondly, in the paper, it mentions that descriptors of two separate images are compared by a simple Euclidean distance - therefore, by taking the Euclidean distance between the two descriptors mentioned above, the Euclidean distance would apparently be 0.
I quickly put together some Javascript code to test out the algorithm, which is below.
Does anybody have any input, ideas, ways to move forward?
Thanks,
Paul
var iShape = [
0, 0, 0, 0, 0,
0, 0, 255, 0, 0,
0, 255, 255, 255, 0,
0, 0, 255, 0, 0,
0, 0, 0, 0, 0
];
var ImageWidth = 5, ImageHeight = 5, MaxRFreq = 5, MaxAFreq = 5;
// Calculate centroid
var cX = 0, cY = 0, pCount = 0;
for (x = 0; x < ImageWidth; x++) {
for (y = 0; y < ImageHeight; y++) {
if (iShape[y * ImageWidth + x]) {
cX += x;
cY += y;
pCount++;
}
}
}
cX = cX / pCount;
cY = cY / pCount;
console.log("cX = " + cX + ", cY = " + cY);
// Calculate the maximum radius
var maxR = 0;
for (x = 0; x < ImageWidth; x++) {
for (y = 0; y < ImageHeight; y++) {
if (iShape[y * ImageWidth + x]) {
var r = Math.sqrt(Math.pow(x - cX, 2) + Math.pow(y - cY, 2));
if (r > maxR) {
maxR = r;
}
}
}
}
// Initialise real / imaginary table
var i;
var FR = [ ];
var FI = [ ];
for (r = 0; r < (MaxRFreq); r++) {
var rRow = [ ];
FR.push(rRow);
var aRow = [ ];
FI.push(aRow);
for (a = 0; a < (MaxAFreq); a++) {
rRow.push(0.0);
aRow.push(0.0);
}
}
var rFreq, aFreq, x, y;
for (rFreq = 0; rFreq < MaxRFreq; rFreq++) {
for (aFreq = 0; aFreq < MaxAFreq; aFreq++) {
for (x = 0; x < ImageWidth; x++) {
for (y = 0; y < ImageHeight; y++) {
var radius = Math.sqrt(Math.pow(x - maxR, 2) +
Math.pow(y - maxR, 2));
var theta = Math.atan2(y - maxR, x - maxR);
if (theta < 0.0) {
theta += (2 * Math.PI);
}
var iPixel = iShape[y * ImageWidth + x];
FR[rFreq][aFreq] += iPixel * Math.cos(2 * Math.PI * rFreq *
(radius / maxR) + aFreq * theta);
FI[rFreq][aFreq] -= iPixel * Math.sin(2 * Math.PI * rFreq *
(radius / maxR) + aFreq * theta);
}
}
}
}
// Initialise fourier descriptor table
var FD = [ ];
for (i = 0; i < (MaxRFreq * MaxAFreq); i++) {
FD.push(0.0);
}
// Calculate the fourier descriptor
for (rFreq = 0; rFreq < MaxRFreq; rFreq++) {
for (aFreq = 0; aFreq < MaxAFreq; aFreq++) {
if (rFreq == 0 && aFreq == 0) {
FD[0] = Math.sqrt(Math.pow(FR[0][0], 2) + Math.pow(FR[0][0], 2) /
(Math.PI * maxR * maxR));
} else {
FD[rFreq * MaxAFreq + aFreq] = Math.sqrt(Math.pow(FR[rFreq][aFreq], 2) +
Math.pow(FI[rFreq][aFreq], 2) / FD[0]);
}
}
}
for (i = 0; i < (MaxRFreq * MaxAFreq); i++) {
console.log(FD[i]);
}
There are three separate normalization techniques applied here in order to make the final descriptor invariant to 1) translation and 2) scale 3) rotation.
For the translation invariance part you need to find the centroid of the shape and calculate the vector of every contour point having the centroid as the origin. This is done by substracting the x and y coordinate of the centroid from each point's coordinates, respectively. So in your code the radius and theta of each point should be computes as follows:
var radius = Math.sqrt(Math.pow(x - cX, 2) + Math.pow(y - cY, 2));
var theta = Math.atan2(y - cY, x - cX);
For the scale invariance part you need to find the maximum magnitute(or radius as you say) of every vector (already normalized for translation invariance) and divide the magnitude of each point by the maximum magnitude value. An alternative way of achieving this is to divide every fourier coefficient with the zero-frequency coefficient (first coefficient) as the scale information is represented there. As I can see in you code and in the paper, this is implemented according to the second way I described.
Finally, the rotation invariance is achieved by only keeping the magnitude of the fourier coefficients as you can see in step 6 of the paper's pseudo-code.
In addition to all these, keep in mind that in order to apply the eucidean distance for the descriptor comparison, the length of the descriptor for every shape must be the same. In FFT, the number of the final coefficients depends on the number of the contour points of the shape. The solution I have found to this is to interpolate between points in order to reach a fixed number of points for every shape.
Hope I helped,
Lazaros
I am trying to make some objects, say 12, to rotate in an ellipse path continuously in Processing. I got a sketch which does rotation in a circle and I want to make it to rotate in a ellipse. I have some pointer from processing forum but the code from the pointer is different from the code that I posted and I couldn't understand yet (weak in trigonometry).
I googled a bit and found a post trying to achieve this with this algorithm:
You need to define your ellipse with a few parameters:
x, y: center of the ellipse
a, b: semimajor and semiminor axes
If you want to move on the elipses this means that you change the
angle between the major axes and your position on the ellipse. Lets
call this angle alpha.
Your position (X,Y) is:
X = x + (a * Math.cos(alpha));
Y = y + (b * Math.sin(alpha));
In order to move left or right you need to increase/decrease alpha and
then recalculate your position. Source:
http://answers.unity3d.com/questions/27620/move-object-allong-an-ellipsoid-path.html
How do I integrate it into my sketch? Thank you.
Here's my sketch:
void setup()
{
size(1024, 768);
textFont(createFont("Arial", 30));
}
void draw()
{
background(0);
stroke(255);
int cx = 500;
int cy = 350;
int r = 300; //radius of the circle
float t = millis()/4000.0f; //increase to slow down the movement
ellipse(cx, cy, 5, 5);
for (int i = 1 ; i <= 12; i++) {
t = t + 100;
int x = (int)(cx + r * cos(t));
int y = (int)(cy + r * sin(t));
line(cx, cy, x, y);
textSize(30);
text(i, x, y);
if (i == 10) {
textSize(15);
text("x: " + x + " y: " + y, x - 50, y - 20);
}
}
}
Replace
int r = 300; //radius of the circle
with
int a = 350; // major axis of ellipse
int b = 250; // minor axis of ellipse
and replace
int x = (int)(cx + r * cos(t));
int y = (int)(cy + r * sin(t));
with
int x = (int)(cx + a * cos(t));
int y = (int)(cy + b * sin(t));
first post here, and probably an easy one.
I've got the code from Processing's reference site:
float a = 0.0;
float inc = TWO_PI/25.0;
for(int i=0; i<100; i=i+4) {
line(i, 50, i, 50+sin(a)*40.0);
a = a + inc;
}
http://processing.org/reference/sin_.html
However, what I need is a line that follows the curve of a Sin wave, not lines representing points along the curve and ending at the 0 axis. So basically I need to draw an "S" shape with a sin wave equation.
Can someone run me through how to do this?
Thank you in advance,
-Askee
To draw a curve you need to store the previous point's position.
float a = 0.0;
float inc = TWO_PI/25.0;
float prev_x = 0, prev_y = 50, x, y;
for(int i=0; i<100; i=i+4) {
x = i;
y = 50 + sin(a) * 40.0;
line(prev_x, prev_y, x, y);
prev_x = x;
prev_y = y;
a = a + inc;
}
If you have a circle with center (center_x, center_y) and radius radius, how do you test if a given point with coordinates (x, y) is inside the circle?
In general, x and y must satisfy (x - center_x)² + (y - center_y)² < radius².
Please note that points that satisfy the above equation with < replaced by == are considered the points on the circle, and the points that satisfy the above equation with < replaced by > are considered the outside the circle.
Mathematically, Pythagoras is probably a simple method as many have already mentioned.
(x-center_x)^2 + (y - center_y)^2 < radius^2
Computationally, there are quicker ways. Define:
dx = abs(x-center_x)
dy = abs(y-center_y)
R = radius
If a point is more likely to be outside this circle then imagine a square drawn around it such that it's sides are tangents to this circle:
if dx>R then
return false.
if dy>R then
return false.
Now imagine a square diamond drawn inside this circle such that it's vertices touch this circle:
if dx + dy <= R then
return true.
Now we have covered most of our space and only a small area of this circle remains in between our square and diamond to be tested. Here we revert to Pythagoras as above.
if dx^2 + dy^2 <= R^2 then
return true
else
return false.
If a point is more likely to be inside this circle then reverse order of first 3 steps:
if dx + dy <= R then
return true.
if dx > R then
return false.
if dy > R
then return false.
if dx^2 + dy^2 <= R^2 then
return true
else
return false.
Alternate methods imagine a square inside this circle instead of a diamond but this requires slightly more tests and calculations with no computational advantage (inner square and diamonds have identical areas):
k = R/sqrt(2)
if dx <= k and dy <= k then
return true.
Update:
For those interested in performance I implemented this method in c, and compiled with -O3.
I obtained execution times by time ./a.out
I implemented this method, a normal method and a dummy method to determine timing overhead.
Normal: 21.3s
This: 19.1s
Overhead: 16.5s
So, it seems this method is more efficient in this implementation.
// compile gcc -O3 <filename>.c
// run: time ./a.out
#include <stdio.h>
#include <stdlib.h>
#define TRUE (0==0)
#define FALSE (0==1)
#define ABS(x) (((x)<0)?(0-(x)):(x))
int xo, yo, R;
int inline inCircle( int x, int y ){ // 19.1, 19.1, 19.1
int dx = ABS(x-xo);
if ( dx > R ) return FALSE;
int dy = ABS(y-yo);
if ( dy > R ) return FALSE;
if ( dx+dy <= R ) return TRUE;
return ( dx*dx + dy*dy <= R*R );
}
int inline inCircleN( int x, int y ){ // 21.3, 21.1, 21.5
int dx = ABS(x-xo);
int dy = ABS(y-yo);
return ( dx*dx + dy*dy <= R*R );
}
int inline dummy( int x, int y ){ // 16.6, 16.5, 16.4
int dx = ABS(x-xo);
int dy = ABS(y-yo);
return FALSE;
}
#define N 1000000000
int main(){
int x, y;
xo = rand()%1000; yo = rand()%1000; R = 1;
int n = 0;
int c;
for (c=0; c<N; c++){
x = rand()%1000; y = rand()%1000;
// if ( inCircle(x,y) ){
if ( inCircleN(x,y) ){
// if ( dummy(x,y) ){
n++;
}
}
printf( "%d of %d inside circle\n", n, N);
}
You can use Pythagoras to measure the distance between your point and the centre and see if it's lower than the radius:
def in_circle(center_x, center_y, radius, x, y):
dist = math.sqrt((center_x - x) ** 2 + (center_y - y) ** 2)
return dist <= radius
EDIT (hat tip to Paul)
In practice, squaring is often much cheaper than taking the square root and since we're only interested in an ordering, we can of course forego taking the square root:
def in_circle(center_x, center_y, radius, x, y):
square_dist = (center_x - x) ** 2 + (center_y - y) ** 2
return square_dist <= radius ** 2
Also, Jason noted that <= should be replaced by < and depending on usage this may actually make sense even though I believe that it's not true in the strict mathematical sense. I stand corrected.
boolean isInRectangle(double centerX, double centerY, double radius,
double x, double y)
{
return x >= centerX - radius && x <= centerX + radius &&
y >= centerY - radius && y <= centerY + radius;
}
//test if coordinate (x, y) is within a radius from coordinate (center_x, center_y)
public boolean isPointInCircle(double centerX, double centerY,
double radius, double x, double y)
{
if(isInRectangle(centerX, centerY, radius, x, y))
{
double dx = centerX - x;
double dy = centerY - y;
dx *= dx;
dy *= dy;
double distanceSquared = dx + dy;
double radiusSquared = radius * radius;
return distanceSquared <= radiusSquared;
}
return false;
}
This is more efficient, and readable. It avoids the costly square root operation. I also added a check to determine if the point is within the bounding rectangle of the circle.
The rectangle check is unnecessary except with many points or many circles. If most points are inside circles, the bounding rectangle check will actually make things slower!
As always, be sure to consider your use case.
You should check whether the distance from the center of the circle to the point is smaller than the radius
using Python
if (x-center_x)**2 + (y-center_y)**2 <= radius**2:
# inside circle
Find the distance between the center of the circle and the points given. If the distance between them is less than the radius then the point is inside the circle.
if the distance between them is equal to the radius of the circle then the point is on the circumference of the circle.
if the distance is greater than the radius then the point is outside the circle.
int d = r^2 - ((center_x-x)^2 + (center_y-y)^2);
if(d>0)
print("inside");
else if(d==0)
print("on the circumference");
else
print("outside");
Calculate the Distance
D = Math.Sqrt(Math.Pow(center_x - x, 2) + Math.Pow(center_y - y, 2))
return D <= radius
that's in C#...convert for use in python...
As said above -- use Euclidean distance.
from math import hypot
def in_radius(c_x, c_y, r, x, y):
return math.hypot(c_x-x, c_y-y) <= r
The equation below is a expression that tests if a point is within a given circle where xP & yP are the coordinates of the point, xC & yC are the coordinates of the center of the circle and R is the radius of that given circle.
If the above expression is true then the point is within the circle.
Below is a sample implementation in C#:
public static bool IsWithinCircle(PointF pC, Point pP, Single fRadius){
return Distance(pC, pP) <= fRadius;
}
public static Single Distance(PointF p1, PointF p2){
Single dX = p1.X - p2.X;
Single dY = p1.Y - p2.Y;
Single multi = dX * dX + dY * dY;
Single dist = (Single)Math.Round((Single)Math.Sqrt(multi), 3);
return (Single)dist;
}
This is the same solution as mentioned by Jason Punyon, but it contains a pseudo-code example and some more details. I saw his answer after writing this, but I didn't want to remove mine.
I think the most easily understandable way is to first calculate the distance between the circle's center and the point. I would use this formula:
d = sqrt((circle_x - x)^2 + (circle_y - y)^2)
Then, simply compare the result of that formula, the distance (d), with the radius. If the distance (d) is less than or equal to the radius (r), the point is inside the circle (on the edge of the circle if d and r are equal).
Here is a pseudo-code example which can easily be converted to any programming language:
function is_in_circle(circle_x, circle_y, r, x, y)
{
d = sqrt((circle_x - x)^2 + (circle_y - y)^2);
return d <= r;
}
Where circle_x and circle_y is the center coordinates of the circle, r is the radius of the circle, and x and y is the coordinates of the point.
My answer in C# as a complete cut & paste (not optimized) solution:
public static bool PointIsWithinCircle(double circleRadius, double circleCenterPointX, double circleCenterPointY, double pointToCheckX, double pointToCheckY)
{
return (Math.Pow(pointToCheckX - circleCenterPointX, 2) + Math.Pow(pointToCheckY - circleCenterPointY, 2)) < (Math.Pow(circleRadius, 2));
}
Usage:
if (!PointIsWithinCircle(3, 3, 3, .5, .5)) { }
As stated previously, to show if the point is in the circle we can use the following
if ((x-center_x)^2 + (y - center_y)^2 < radius^2) {
in.circle <- "True"
} else {
in.circle <- "False"
}
To represent it graphically we can use:
plot(x, y, asp = 1, xlim = c(-1, 1), ylim = c(-1, 1), col = ifelse((x-center_x)^2 + (y - center_y)^2 < radius^2,'green','red'))
draw.circle(0, 0, 1, nv = 1000, border = NULL, col = NA, lty = 1, lwd = 1)
Moving into the world of 3D if you want to check if a 3D point is in a Unit Sphere you end up doing something similar. All that is needed to work in 2D is to use 2D vector operations.
public static bool Intersects(Vector3 point, Vector3 center, float radius)
{
Vector3 displacementToCenter = point - center;
float radiusSqr = radius * radius;
bool intersects = displacementToCenter.magnitude < radiusSqr;
return intersects;
}
iOS 15, Accepted Answer written in Swift 5.5
func isInRectangle(center: CGPoint, radius: Double, point: CGPoint) -> Bool
{
return point.x >= center.x - radius && point.x <= center.x + radius &&
point.y >= center.y - radius && point.y <= center.y + radius
}
//test if coordinate (x, y) is within a radius from coordinate (center_x, center_y)
func isPointInCircle(center: CGPoint,
radius:Double, point: CGPoint) -> Bool
{
if(isInRectangle(center: center, radius: radius, point: point))
{
var dx:Double = center.x - point.x
var dy:Double = center.y - point.y
dx *= dx
dy *= dy
let distanceSquared:Double = dx + dy
let radiusSquared:Double = radius * radius
return distanceSquared <= radiusSquared
}
return false
}
I used the code below for beginners like me :).
public class incirkel {
public static void main(String[] args) {
int x;
int y;
int middelx;
int middely;
int straal; {
// Adjust the coordinates of x and y
x = -1;
y = -2;
// Adjust the coordinates of the circle
middelx = 9;
middely = 9;
straal = 10;
{
//When x,y is within the circle the message below will be printed
if ((((middelx - x) * (middelx - x))
+ ((middely - y) * (middely - y)))
< (straal * straal)) {
System.out.println("coordinaten x,y vallen binnen cirkel");
//When x,y is NOT within the circle the error message below will be printed
} else {
System.err.println("x,y coordinaten vallen helaas buiten de cirkel");
}
}
}
}}
Here is the simple java code for solving this problem:
and the math behind it : https://math.stackexchange.com/questions/198764/how-to-know-if-a-point-is-inside-a-circle
boolean insideCircle(int[] point, int[] center, int radius) {
return (float)Math.sqrt((int)Math.pow(point[0]-center[0],2)+(int)Math.pow(point[1]-center[1],2)) <= radius;
}
PHP
if ((($x - $center_x) ** 2 + ($y - $center_y) ** 2) <= $radius **2) {
return true; // Inside
} else {
return false; // Outside
}