Se hai un cerchio con centro (center_x, center_y)
e raggio radius
, come fai a verificare se un determinato punto con coordinate si (x, y)
trova all'interno del cerchio?
Se hai un cerchio con centro (center_x, center_y)
e raggio radius
, come fai a verificare se un determinato punto con coordinate si (x, y)
trova all'interno del cerchio?
Risposte:
In generale, x
e y
deve soddisfare (x - center_x)^2 + (y - center_y)^2 < radius^2
.
Si noti che i punti che soddisfano l'equazione di cui sopra con <
sostituiti da ==
vengono considerati i punti sul cerchio e i punti che soddisfano l'equazione di cui sopra con <
sostituiti da >
vengono considerati all'esterno del cerchio.
<=
troveranno punti all'interno del cerchio o sul bordo.
Matematicamente, Pitagora è probabilmente un metodo semplice come molti hanno già menzionato.
(x-center_x)^2 + (y - center_y)^2 < radius^2
Computazionalmente, ci sono modi più rapidi. Definire:
dx = abs(x-center_x)
dy = abs(y-center_y)
R = radius
Se è più probabile che un punto si trovi all'esterno di questo cerchio, immagina un quadrato disegnato attorno ad esso in modo tale che i suoi lati siano tangenti a questo cerchio:
if dx>R then
return false.
if dy>R then
return false.
Ora immagina un diamante quadrato disegnato all'interno di questo cerchio in modo tale che i suoi vertici tocchino questo cerchio:
if dx + dy <= R then
return true.
Ora abbiamo coperto la maggior parte del nostro spazio e solo una piccola area di questo cerchio rimane tra il nostro quadrato e il diamante da testare. Qui torniamo a Pitagora come sopra.
if dx^2 + dy^2 <= R^2 then
return true
else
return false.
Se è più probabile che un punto si trovi all'interno di questo cerchio, inverti l'ordine dei primi 3 passaggi:
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.
Metodi alternativi immaginano un quadrato all'interno di questo cerchio anziché un diamante, ma ciò richiede leggermente più test e calcoli senza alcun vantaggio computazionale (il quadrato interno e i diamanti hanno aree identiche):
k = R/sqrt(2)
if dx <= k and dy <= k then
return true.
Aggiornare:
Per coloro che sono interessati alle prestazioni, ho implementato questo metodo in c e compilato con -O3.
Ho ottenuto i tempi di esecuzione di time ./a.out
Ho implementato questo metodo, un metodo normale e un metodo fittizio per determinare i tempi di consegna.
Normal: 21.3s
This: 19.1s
Overhead: 16.5s
Quindi, sembra che questo metodo sia più efficiente in questa implementazione.
// 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);
}
inCircleN
stai usando ABS non necessari. Probabilmente senza ABS differenza tra inCircle
e inCircleN
sarebbe più piccolo.
Puoi usare Pitagora per misurare la distanza tra il tuo punto e il centro e vedere se è inferiore al raggio:
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 (punta di cappello a Paul)
In pratica, la quadratura è spesso molto più economica rispetto alla radice quadrata e poiché siamo interessati solo a un ordinamento, possiamo ovviamente rinunciare a prendere la radice quadrata:
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
Inoltre, Jason ha notato che <=
dovrebbe essere sostituito da <
e, a seconda dell'uso, questo potrebbe effettivamente avere sensoanche se credo che non sia vero in senso matematico rigoroso. Sono corretto.
**
o ^
. Il modo più veloce per farlo quando basta x ^ 2 o x ^ 3 è quello di farlo "manualmente": x*x
.
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;
}
Questo è più efficiente e leggibile. Evita la costosa operazione di radice quadrata. Ho anche aggiunto un segno di spunta per determinare se il punto si trova all'interno del rettangolo di delimitazione del cerchio.
Il controllo del rettangolo non è necessario se non con molti punti o molti cerchi. Se la maggior parte dei punti sono all'interno dei cerchi, il controllo del rettangolo di delimitazione renderà le cose più lente!
Come sempre, assicurati di considerare il tuo caso d'uso.
Calcola la distanza
D = Math.Sqrt(Math.Pow(center_x - x, 2) + Math.Pow(center_y - y, 2))
return D <= radius
che è in C # ... converti per l'uso in Python ...
Come detto sopra, usa la distanza euclidea.
from math import hypot
def in_radius(c_x, c_y, r, x, y):
return math.hypot(c_x-x, c_y-y) <= r
Trova la distanza tra il centro del cerchio e i punti indicati. Se la distanza tra loro è inferiore al raggio, il punto si trova all'interno del cerchio. se la distanza tra loro è uguale al raggio del cerchio, allora il punto è sulla circonferenza del cerchio. se la distanza è maggiore del raggio, il punto si trova all'esterno del cerchio.
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");
L'equazione seguente è un'espressione che verifica se un punto si trova all'interno di un determinato cerchio in cui xP e yP sono le coordinate del punto, xC e yC sono le coordinate del centro del cerchio e R è il raggio di quel determinato cerchio.
Se l'espressione sopra è vera, il punto è all'interno del cerchio.
Di seguito è riportata un'implementazione di esempio 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;
}
Questa è la stessa soluzione menzionata da Jason Punyon , ma contiene un esempio di pseudo-codice e alcuni dettagli in più. Ho visto la sua risposta dopo aver scritto questo, ma non volevo rimuovere la mia.
Penso che il modo più facilmente comprensibile sia calcolare prima la distanza tra il centro del cerchio e il punto. Vorrei usare questa formula:
d = sqrt((circle_x - x)^2 + (circle_y - y)^2)
Quindi, confronta semplicemente il risultato di quella formula, la distanza ( d
), con il radius
. Se la distanza ( d
) è inferiore o uguale al raggio ( r
), il punto si trova all'interno del cerchio (sul bordo del cerchio se d
e r
sono uguali).
Ecco un esempio di pseudo-codice che può essere facilmente convertito in qualsiasi linguaggio di programmazione:
function is_in_circle(circle_x, circle_y, r, x, y)
{
d = sqrt((circle_x - x)^2 + (circle_y - y)^2);
return d <= r;
}
Dove circle_x
e circle_y
sono le coordinate centrali del cerchio, r
è il raggio del cerchio x
ed y
è le coordinate del punto.
La mia risposta in C # come soluzione completa taglia e incolla (non ottimizzata):
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));
}
Uso:
if (!PointIsWithinCircle(3, 3, 3, .5, .5)) { }
Come affermato in precedenza, per mostrare se il punto è nel cerchio possiamo usare quanto segue
if ((x-center_x)^2 + (y - center_y)^2 < radius^2) {
in.circle <- "True"
} else {
in.circle <- "False"
}
Per rappresentarlo graficamente possiamo usare:
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)
Ho usato il codice qui sotto per i principianti come 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");
}
}
}
}}
Spostandoti nel mondo del 3D se vuoi verificare se un punto 3D si trova in una Sfera Unità, finisci per fare qualcosa di simile. Tutto ciò che serve per lavorare in 2D è usare le operazioni vettoriali 2D.
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;
}
So che mancano pochi anni alla risposta più votata, ma sono riuscito a ridurre i tempi di calcolo di 4.
Devi solo calcolare i pixel da 1/4 del cerchio, quindi moltiplicarli per 4.
Questa è la soluzione che ho raggiunto:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int x, y, r;
int mx, c, t;
int dx, dy;
int p;
int main() {
for (r = 1; r < 128; r++){
clock_t t;
t = clock();
p = calculatePixels(r);
t = clock() - t;
double time_taken = ((double)t)/CLOCKS_PER_SEC; // in seconds
printf( "%d of pixels inside circle with radius %d, took %f seconds to execute \n", p, r, time_taken);
}
}
int calculatePixels(int r){
mx = 2 * r;
c = (mx+1)*(mx+1);
t = r * r;
int a = 0;
for (x = 0; x < r; x++){
for (y = 0; y < r; y++){
dx = x-r;
dy = y-r;
if ((dx*dx + dy*dy) > t)
a++;
else
y = r;
}
}
return (c - (a * 4));
}
Ecco il semplice codice Java per risolvere questo problema:
e la matematica dietro: /math/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;
}