Autor Tema: Intersección de DOS Círculos Secantes

0 Usuarios y 1 Visitante están viendo este tema.

01 Mayo, 2020, 08:34 pm
Leído 813 veces

MasLibertad

  • $$\Large \color{#5372a0}\pi\,\pi$$
  • Mensajes: 63
  • Karma: +0/-0
  • Sexo: Masculino
    • Más Libertad
Hola a todos. Llevaba varios días queriendo entrar pero el foro daba fallo. Me alegro de que por fin se haya arreglado.

Estoy programando una nueva herramienta para mi página y para ello debo resolver un problema de geometría.
Tenemos dos Círculos S y P, con coordenadas y radio Sx, Sy, Sr, Px, Py, Pr.
El círculo P, menor que S, puede ser externo, interno o secante.
En el caso de ser secante ¿Cuál es la superficie de la intersección?

El problema lo he descompuesto en dos partes.
La segunda parte la he resuelto de la siguiente forma:
Tenemos un sector circular ASB y un triángulo ASB. Restando ambas cantidades tendremos UN trozo del área común. Si ahora hacemos lo mismo con el sector APB y el triángulo APB tendremos el OTRO trozo del área común. Sumándolas, tendremos la superficie común de ambos círculos. Relativamente, ha sido fácil.

El problema lo tengo con la primera parte:
¿Cómo calculo las coordenadas de A y B?
¿O los ángulos ASB y APB?
No he encontrado en ninguna parte una fórmula directa para calcularlo. Sí he visto varios ejemplos (por ejemplo, en Youtube: Intersección de Dos Circunferencias) que se han ido desarrollando paso a paso hasta alcanzar la solución, pero cuando he querido convertir estos desarrollos en una fórmula general me he topado con lo siguiente:
En Wikipedia: Ecuación de la Circunferencia, encuentro lo siguiente:
\( (x-a)^2 + (y-b)^2 = r^2 \)
Aplicado a mi problema tendríamos dos ecuaciones:
\( (x-Sx)^2 + (y-Sy)^2 = Sr^2 \)
y
\( (x-Px)^2 + (y-Py)^2 = Pr^2 \)

Después de desarrollarlas, igualarlas a CERO, igualarlas entre sí y simplificar, he llegado a:
\( Sx^2-2x*Sx + Sy^2-2y*Sy - Sr^2 = Px^2-2x*Px + Py^2-2y*Py - Pr^2 \)

Y hasta aquí he llegado yo.
La verdad, resolver este problema para un caso particular es relativamente fácil porque podemos ir realizando cálculos y simplificando la fórmula en cada paso, cosa que en programación, para una fórmula general, no puedo hacer pues tengo que tener TODAS las variables, que no se me escape ninguna y que no me equivoque en un signo.
Pero hay un problema mayor, y es que al final de este proceso hay que realizar un par de conversiones y sustituciones que mentalmente son fáciles de dar, pero que no tengo ni idea de cómo programar.
Como el foro ha estado tiempo sin funcionar, se me ha ocurrido hacer trampa, calcular A y B no por fórmulas, sino por programación, y ya tenía pensada la forma de hacerlo y completar el programa cuando he visto que ¡POR FIN! vuelven a funcionar los foros.
Así que daré una oportunidad más a las matemáticas.

¿Existe alguna fórmula más sencillita de calcular las coordenadas de A y  B en el gráfico adjunto?
O ¿de calcular directamente el área común a dos círculos secantes?

Espero que podáis ayudarme, si no, me veré obligado a hacer trampas.
Siempre hay un medio si el Valor va unido a la Inteligencia
Conan el BárbaroLa Torre del Elefante

02 Mayo, 2020, 01:42 am
Respuesta #1

Abdulai

  • Moderador Global
  • Mensajes: 2,479
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
....
Estoy programando una nueva herramienta para mi página y para ello debo resolver un problema de geometría.
Tenemos dos Círculos S y P, con coordenadas y radio Sx, Sy, Sr, Px, Py, Pr.
El círculo P, menor que S, puede ser externo, interno o secante.
En el caso de ser secante ¿Cuál es la superficie de la intersección?
.....
.....
El problema lo tengo con la primera parte:
¿Cómo calculo las coordenadas de A y B?
¿O los ángulos ASB y APB?

Aplicando el teorema del coseno y Pitágoras podés calcular \( AB \) , \( SQ \) y \( PQ \) . Siendo \( Q \) el punto de intersección entre \( AB \) y \( SP \)
Con esas medidas ya podés calcular la superficie de los sectores circulares y los triángulos.


Hace mucho me encontré con un problema parecido de intersección de círculos y al procedimiento anterior lo simpliqué para un codigo en C.

Como encontré el código, copypego el algoritmo con adaptaciones a tu problema y notación.

Código: (C) [Seleccionar]
// Datos en
double  Sx,Sy,Sr , Px,Py,Pr ;

//------------------------------------
// Variables locales
    double dx,dy,l,s,d,p,q ;
    double p1,p2,A ;
//--   
    dx = Px-Sx ;
    dy = Py-Sy ;
    l  = sqrt(dx*dx+dy*dy) ;

    s = (Sr+Pr)/l ;
    d = (Sr-Pr)/l ;

    p= s*d ;
    q= sqrt((s*s-1)*(1-d*d))/2 ;
 
    p1 = (1+p)/2 ;
    p2 = (1-p)/2 ;
     
//  A = Suma de las áreas de cada sector
    A  = Sr*Sr*atan(q/p1) - l*l*p1*q +
         Pr*Pr*atan(q/p2) - l*l*p2*q ; 
//------------------------------------


Si necesitaras las coordenadas de los puntos A y B, el procedimiento es el mismo y la primer parte del código también.

Código: (C) [Seleccionar]
// Datos en
double  Sx,Sy,Sr , Px,Py,Pr ; 

//------------------------------------
// Variables locales
    double dx,dy,l,s,d,p,q ;
    double Ax,Ay,Bx,By ;
//--
    dx = Px-Sx ;
    dy = Py-Sy ;
    l  = sqrt(dx*dx+dy*dy) ;

    s = (Sr+Pr)/l ;
    d = (Sr-Pr)/l ;

    p= s*d ;
    q= sqrt((s*s-1)*(1-d*d))/2 ;

//  Cálculo de las coordenadas de
//  los puntos A=(Ax,Ay), B=(Bx,By)
//--
    Ax = Bx = (Px+Sx+dx*p)/2 ;
    Ay = By = (Py+Sy+dy*p)/2 ;

    dx *= q  ;  dy *= q ;
    Ax -= dy ;  Ay += dx ;
    Bx += dy ;  By -= dx ;
//------------------------------------

Citar
...
Como el foro ha estado tiempo sin funcionar, se me ha ocurrido hacer trampa, calcular A y B no por fórmulas, sino por programación, y ya tenía pensada la forma de hacerlo y completar el programa cuando he visto que ¡POR FIN! vuelven a funcionar los foros.
Así que daré una oportunidad más a las matemáticas.

No entiendo a que te estás refiriendo con: no por fórmulas, sino por programación

02 Mayo, 2020, 08:46 am
Respuesta #2

hméndez

  • $$\Large \color{#5e8d56}\pi\,\pi\,\pi$$
  • Mensajes: 414
  • País: ve
  • Karma: +1/-0
  • Sexo: Masculino
Hola MasLibertad

Fíjate que para que se de la intersección entre los círculos se debe cumplir que la distancia entre sus centros
debe ser mayor que la diferencia de sus radios y menor que su suma.

Si llamas L a la distancia entre los centros, esta se puede calcular como:

\( L=\sqrt[ ]{(Px-Sx)^2+(Py-Sy)^2} \) (ojo con lo que indico arriba)

Los puntos S, A, P determinan un triángulo de lados Sr, Pr, L, del cual puedes calcular con el Teorema del
Coseno el ángulo ASP y en consecuencia el ángulo ASB (que es 2 veces el ángulo ASP), eso te da:

\( ts=2\cdot{}arccos(\frac{L^2+Sr^2-Pr^2}{2\cdot{}L\cdot{}Sr}) \)

Conmutando las variables Sr y Pr en la fórmula anterior obtienes el ángulo APB, eso te da:

\( tp=2\cdot{}arccos(\frac{L^2+Pr^2-Sr^2}{2\cdot{}L\cdot{}Pr}) \)

Para el segmento circular determinado por el círculo S y la cuerda AB tienes un área:

https://es.wikipedia.org/wiki/Segmento_circular#%C3%81rea

\( As=\frac{Sr^2}{2}\cdot{}(ts-sin(ts)) \)

para el correspondiente al circulo P tienes un área:

\( Ap=\frac{Pr^2}{2}\cdot{}(tp-sin(tp)) \)

El área total:

\( At = As+Ap  \)

Corregido

Saludos

P.D. Estas fórmulas también valen para el caso en que el centro de uno de los círculos se encuentra dentro del otro.

02 Mayo, 2020, 09:01 am
Respuesta #3

MasLibertad

  • $$\Large \color{#5372a0}\pi\,\pi$$
  • Mensajes: 63
  • Karma: +0/-0
  • Sexo: Masculino
    • Más Libertad
....
Tenemos dos Círculos S y P, con coordenadas y radio Sx, Sy, Sr, Px, Py, Pr.
El círculo P, menor que S, puede ser externo, interno o secante.
En el caso de ser secante ¿Cuál es la superficie de la intersección?

Código: (C) [Seleccionar]
// Datos en
double  Sx,Sy,Sr , Px,Py,Pr ;

//------------------------------------
// Variables locales
    double dx,dy,l,s,d,p,q ;
    double p1,p2,A ;
//--   
    dx = Px-Sx ;
    dy = Py-Sy ;
    l  = sqrt(dx*dx+dy*dy) ;

    s = (Sr+Pr)/l ;
    d = (Sr-Pr)/l ;

    p= s*d ;
    q= sqrt((s*s-1)*(1-d*d))/2 ;
 
    p1 = (1+p)/2 ;
    p2 = (1-p)/2 ;
     
//  A = Suma de las áreas de cada sector
    A  = Sr*Sr*atan(q/p1) - l*l*p1*q +
         Pr*Pr*atan(q/p2) - l*l*p2*q ; 
//------------------------------------
:o :aplauso:
Muchísimas gracias, Abdulai. Creo que con esto ya podré terminar mi programa sin hacer trampas.

No entiendo a que te estás refiriendo con: no por fórmulas, sino por programación

Código: [Seleccionar]
Para Angulo = 0 hasta 360
   Convertir polares (Angulo,Sr) en cartesianas (x,y)
   Calcular distancia (x,y) hasta (Px,Py)
   Comparar con Pr
   Si ha cambiado de Mayor a Menor: Intersección A = (x,y)
   Si ha cambiado de Menor a Mayor: Intersección B = (x,y)

Lo confieso, es trampa, pero cuando un desarrollo matemático me  :banghead: no me queda otra.

A ver si puedo terminar el programa hoy, lo publico y os lo digo.

Muchísimas gracias.
Siempre hay un medio si el Valor va unido a la Inteligencia
Conan el BárbaroLa Torre del Elefante

02 Mayo, 2020, 09:12 am
Respuesta #4

MasLibertad

  • $$\Large \color{#5372a0}\pi\,\pi$$
  • Mensajes: 63
  • Karma: +0/-0
  • Sexo: Masculino
    • Más Libertad
Hola, hméndez.

Si llamas L a la distancia entre los centros, esta se puede calcular como:
\( L=\sqrt[ ]{(Px-Sx)^2+(Py-Sy)^2} \)
Los puntos S, A, P determinan un triangulo de lados Sr, Pr, L, del cual puedes calcular con el Teorema del coseno el angulo ASP y en consecuencia el angulo ASB (que es 2 veces el angulo ASP), eso te da:
\( ts=arccos(\frac{L^2+Sr^2-Pr^2}{2\cdot{}L\cdot{}Sr}) \)
Conmutando las variables Sr y Pr en la formula anterior obtienes el angulo APB, eso te da:
\( tp=arccos(\frac{L^2+Pr^2-Sr^2}{2\cdot{}L\cdot{}Pr}) \)
Para el segmento circular determinado por el circulo S y la cuerda AB tienes un area:
\( As=\displaystyle\frac{Sr}{2}\cdot{}(ts-sin(ts)) \)
Para el correspondiente al circulo P tienes un area:
\( Ap=\displaystyle\frac{Pr}{2}\cdot{}(tp-sin(tp)) \)
El area total:
\( At = As+Ap  \)

Es otro procedimiento, por lo que veo distinto al que ha indicado Abdulai, que pienso estudiar y probar en mi programa.
A ver si me da tiempo a terminarlo y publicarlo hoy mismo.

Saludos y gracias.
Siempre hay un medio si el Valor va unido a la Inteligencia
Conan el BárbaroLa Torre del Elefante

06 Mayo, 2020, 02:30 pm
Respuesta #5

MasLibertad

  • $$\Large \color{#5372a0}\pi\,\pi$$
  • Mensajes: 63
  • Karma: +0/-0
  • Sexo: Masculino
    • Más Libertad
Hola a todos.

Pues lo he intentado, pero no lo he conseguido todavía.

Os cuento: El programa que estoy haciendo es para calcular cómo disminuye el brillo de una estrella cuando es eclipsado por un planeta. Mi idea es generar una curva similar a esta:

Reduciéndolo a un esquema geométrico que sea fácil de manejar, son DOS círculos S y P (Sol y Planeta), que pueden estar en TRES posiciones: Externa, Interna y Secante.
Cuando están en posición secante es cuando necesito la fórmula que me ha dado Obdulai, y que se lo agradezco.

Pero tras intentar implementarla sin conseguirlo, he ido a lo básico: pura geometría.

Una nueva herramienta, que no había previsto pero que me parece muy interesante, en la que podamos colocar dos círculos y que nos diga la superficie de ambos y de la zona de intersección.
Aquí la tenéis:

Dejando aparte el hecho de que está incompleto (pienso explicar TODO el proceso de cálculo de la fórmula de Abdulai. Si es que consigo entenderlo), la fórmula tiene un fallo que se produce cuando la distancia de P a S es menor que la cuerda de A a B.

Pinchad en una de las barras de rango y usad los cursores, Izq y Der, para mover el círculo, y veréis que en el momento en que el centro de P atraviesa la cuerda AB, el área calculada se vuelve negativa.

¿Cómo? ¿Por qué?
No tengo ni idea, y bien que lo he intentado.

Si podéis echarme una mano en esto os lo agradecería.

Incluyo el código de la función JavaScript para calcular la superficie común a dos círculos:

Código: [Seleccionar]
function SuperficieComun(x,y,r)
{
var d=Math.sqrt(x*x+y*y); // Distancia de Centro a Centro
if (d>1*Sr+r) return 0; // Si Mayor que Suma de Radios: Externo
if (d<1*Sr-r) return PI*r*r; // Si Menor que Resta de Radios, interno
// Si no, secante: Calcular superficie común
var l  = Math.sqrt(x*x+y*y) ;
var s = (Sr+Pr)/l ;
var d = (Sr-Pr)/l ;
var p= s*d ;
var q= Math.sqrt((s*s-1)*(1-d*d))/2 ;
var p1 = (1+p)/2 ;
var p2 = (1-p)/2 ;
 
//  Suma de las áreas de cada sector
var A  = Sr*Sr*Math.atan(q/p1) -
l*l*p1*q + Pr*Pr*Math.atan(q/p2) -
l*l*p2*q ;

//  Cálculo de las coordenadas de
//  los puntos A=(Ax,Ay), B=(Bx,By)
// se almacenan en variables globales Ax, Ay, Bx y By
    Ax = Bx = (Px+Sx+x*p)/2 ;
    Ay = By = (Py+Sy+y*p)/2 ;

    x *= q  ;  y *= q ;
    Ax -= y ;  Ay += x ;
    Bx += y ;  By -= x ;
return A;
}
Siempre hay un medio si el Valor va unido a la Inteligencia
Conan el BárbaroLa Torre del Elefante

06 Mayo, 2020, 04:55 pm
Respuesta #6

Abdulai

  • Moderador Global
  • Mensajes: 2,479
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
...
Dejando aparte el hecho de que está incompleto (pienso explicar TODO el proceso de cálculo de la fórmula de Abdulai. Si es que consigo entenderlo), la fórmula tiene un fallo que se produce cuando la distancia de P a S es menor que la cuerda de A a B.
...

El problema es que Math.atan(x) devuelve un valor entre \( \pm\frac{\pi}{2}  \)

Se soluciona con Math.atan2(y,x) que devuelve entre \( \pm \pi \)

Con la fórmula de hmendez esto no ocurre pues Math.acos(x) devuelve entre \( 0\cdots\pi \).   

Solamente hay que tener en cuenta que algunos lenguajes no incluyen acos() ni asin(), solo atan() y es uno quien debe ajustar el ángulo.
Una forma es viendo en qué cuadrante se está y otra puede ser hacer  \( \theta = 2*\text{atan}\left(\frac{y}{r+x}\right) \)  con   \( r=\displaystyle\sqrt{x^2+y^2} \)


06 Mayo, 2020, 09:05 pm
Respuesta #7

MasLibertad

  • $$\Large \color{#5372a0}\pi\,\pi$$
  • Mensajes: 63
  • Karma: +0/-0
  • Sexo: Masculino
    • Más Libertad
Hola, Abdulai

Con la corrección que me has hecho, el programa ya está corregido y publicado, y por lo que parece funciona bien.
Si queréis verlo: Intersección de Círculos Secantes

Lo que me falta es el texto del artículo, explicar cómo se llega a esa fórmula tan compleja para mí, por lo que tendré que estudiarla paso a paso y cuando sea capaz de entenderla seré capaz de explicarla. Espero.

Una duda: en tu proceso indicaste
Código: [Seleccionar]
var l  = Math.sqrt(x*x+y*y) ;
...
//  Suma de las áreas de cada sector
var A  = Sr*Sr*Math.atan(q/p1) -
l*l*p1*q + Pr*Pr*Math.atan(q/p2) -
l*l*p2*q ;
Yo he cambiado, tal como me has dicho, el último cálculo por
Código: [Seleccionar]
var A  = Sr*Sr*Math.atan2(q,p1) -
l*l*p1*q + Pr*Pr*Math.atan2(q,p2) -
l*l*p2*q ;
Pero a lo que voy es que usas dos veces l*l, y siendo l=Math.sqrt(x*x+y*y), ¿no sería más simple usar una variable intermedia (il=x*x+y*y) y luego usar sólo il, en vez de l*l ?
¿O lo has hecho así porque el proceso es más comprensible al dibujar el gráfico?
De cualquier forma, te agradezco la ayuda.
Un saludo. ¡¡Con signos de admiración!!
Siempre hay un medio si el Valor va unido a la Inteligencia
Conan el BárbaroLa Torre del Elefante

06 Mayo, 2020, 09:53 pm
Respuesta #8

Abdulai

  • Moderador Global
  • Mensajes: 2,479
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
...
Lo que me falta es el texto del artículo, explicar cómo se llega a esa fórmula tan compleja para mí, por lo que tendré que estudiarla paso a paso y cuando sea capaz de entenderla seré capaz de explicarla. Espero.

Mi problema original era solamente calcular las coordenadas de las intersecciones evitando usar funciones trigonométricas.
Lo que hice fue tomar el código y agregar el cálculo del área.  Claro que como para el área del sector circular necesitás si o si una trigonométrica inversa pierde sentido evitarlas.
Ademas, si solamente se busca el área, hay resultados intermedios que pueden evitarse y verse el cálculo mas claro  (ver mensaje de hmendez)

Citar
Una duda: en tu proceso indicaste
Código: [Seleccionar]
var l  = Math.sqrt(x*x+y*y) ;
...
//  Suma de las áreas de cada sector
var A  = Sr*Sr*Math.atan(q/p1) -
l*l*p1*q + Pr*Pr*Math.atan(q/p2) -
l*l*p2*q ;
Yo he cambiado, tal como me has dicho, el último cálculo por
Código: [Seleccionar]
var A  = Sr*Sr*Math.atan2(q,p1) -
l*l*p1*q + Pr*Pr*Math.atan2(q,p2) -
l*l*p2*q ;
Pero a lo que voy es que usas dos veces l*l, y siendo l=Math.sqrt(x*x+y*y), ¿no sería más simple usar una variable intermedia (il=x*x+y*y) y luego usar sólo il, en vez de l*l ?
¿O lo has hecho así porque el proceso es más comprensible al dibujar el gráfico?

Sumé las áres individuales sin simplificar.
Podés escribirlo como:

Código: [Seleccionar]
var l2 = x*x+y*y ;
var l  = Math.sqrt(l2) ;
..........
..........
..........
var A  = Sr*Sr*Math.atan2(q,p1) + Pr*Pr*Math.atan2(q,p2) - l2*q*(p1+p2) ;


Un saludo!