Saltar al contenido

Dado un círculo de radio r, y dos puntos (‘X’ y ‘Z’) en ese círculo, ¿se puede construir algún arco circuncircular “XYZ” de longitud r?

Después de tanto batallar ya encontramos la respuesta de este atascamiento que ciertos de nuestros lectores de este espacio tienen. Si tienes algún detalle que compartir puedes dejar tu información.

Solución:

El punto $ Y $ existirá. Habrá dos puntos que satisfagan el requisito, uno a cada lado de $ XZ $. Puedes demostrarlo usando el teorema del valor intermedio. El segmento $ XZ $ es demasiado corto y el arco con un $ Y $ propuesto lejos será demasiado largo, por lo que hay un punto intermedio que es el correcto. Estoy seguro de que generalmente no se podrá construir con brújula y regla, pero no conozco una manera fácil de demostrarlo.

Ciertamente, esta no es una respuesta aceptable. Pero quizás una contribución útil. Acabo de piratear un pequeño programa en el que puedes arrastrar los puntos x / z e imprime parte de la información relevante.

En particular, imprime el ángulo entre OX y OZ, y la longitud relativa de la línea OY (refiriéndose al radio).

ingrese la descripción de la imagen aquí

Como ya notó, la solución solo puede existir para un ángulo que no sea mayor de 60 °. (Para 60 °, el resultado será solo el círculo original). En este caso, la distancia de Y a O será 1.0 (¡relativa al radio!).

los más bajo El límite para el ángulo parece ser de aproximadamente 37 °, y la distancia relativa de Y a O será de aproximadamente 1,26. Pero, por supuesto, este cálculo solo da una áspero ¡aproximación!

La implementación está aquí, en Java. Debe ser independiente y se puede compilar e iniciar directamente en cualquier IDE.

Pero Nota: La implementación es De Verdad crudo, así que tómalo con un grano de sal. Particularmente, realiza una búsqueda de “fuerza bruta” para la distancia de Y a la que la longitud del arco resultante será aproximadamente igual al radio. Esto podría o debería mejorarse en muchos formas, por ejemplo, haciendo una búsqueda binaria y / o buscando ambos soluciones que se supone que existen en cada punto.

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class CircumcircleTest

    public static void main(String[] args)
    
        SwingUtilities.invokeLater(() -> createAndShowGui());
    

    private static void createAndShowGui()
    
        JFrame frame = new JFrame();
        frame.getContentPane().add(new CircumcircleTestPanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(1200,800);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    



class CircumcircleTestPanel extends JPanel
    implements MouseListener, MouseMotionListener


    private Point2D center;
    private double radius = 200;

    private Point2D x;
    private Point2D z;

    private Point2D draggedPoint = null;
    private List points;

    CircumcircleTestPanel()
    
        super(null);

        center = new Point2D.Double(300, 300);
        x = new Point2D.Double(center.getX() + radius, center.getY() - radius);
        z = new Point2D.Double(center.getX() + radius, center.getY() + radius);
        validatePoints();

        points = new ArrayList();
        points.add(x);
        points.add(z);

        addMouseListener(this);
        addMouseMotionListener(this);
    


    @Override
    protected void paintComponent(Graphics gr)
    
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;
        g.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,  
            RenderingHints.VALUE_ANTIALIAS_ON);
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, getWidth(), getHeight());

        g.setColor(Color.GRAY);
        drawCircle(g, new Circle(center, radius));

        g.setColor(Color.BLUE);
        drawPoint(g, center, "O");
        drawPoint(g, x, "X");
        drawPoint(g, z, "Z");

        double angleXZ = angle(center, x, center, z);

        g.setColor(Color.BLACK);
        drawLine(g, center, x);
        drawLine(g, center, z);

        g.setColor(Color.GREEN);
        Line2D bisector = computeBisector(center, x, z);
        g.draw(bisector);

        double arcLength = Double.NaN;
        double lengthRelativeToRadius = Double.NaN;

        Point2D y = computeY(bisector);
        if (y != null)
        
            g.setColor(Color.RED);
            drawPoint(g, y, "Y");

            g.setColor(Color.GRAY);
            Circle c = computeCircumcircle(
                x.getX(), x.getY(),
                y.getX(), y.getY(),
                z.getX(), z.getY(), null);
            drawCircle(g, c);

            arcLength = computeArcLength(c.getCenter(), x, z);
            double distanceY = center.distance(y);
            lengthRelativeToRadius = distanceY / radius;
        

        g.setColor(Color.BLACK);
        int tx = 10;
        int ty = 20;
        g.drawString("angleXZ: "+Math.toDegrees(angleXZ), tx, ty+=20);
        g.drawString("arcLength: "+arcLength, tx, ty+=20);
        g.drawString("lengthRelativeToRadius: "+lengthRelativeToRadius, 
            tx, ty+=20);

    


    private Point2D computeY(Line2D bisector)
    
        double minDeviation = Double.POSITIVE_INFINITY;
        Point2D closestY = null;
        double minDistanceToCenter = Double.POSITIVE_INFINITY;
        int n = 10000;
        for (int i=n; i points)
    
        for (Point2D point : points)
        
            drawPoint(g, point, "x");
        
    

    private static void drawPoint(Graphics2D g, Point2D point, String label)
    
        double r = 3;
        double x = point.getX();
        double y = point.getY();
        g.fill(new Ellipse2D.Double(x-r, y-r, r+r, r+r));
        g.drawString(label, (int)(x+10), (int)(y+10));
    

    private static void drawLine(Graphics2D g, Point2D p0, Point2D p1)
    
        g.draw(new Line2D.Double(p0,p1));
    

    private static void drawCircle(Graphics2D g, Circle c)
    
        g.draw(new Ellipse2D.Double(
            c.getCenter().getX()-c.getRadius(),
            c.getCenter().getY()-c.getRadius(),
            c.getRadius()+c.getRadius(),
            c.getRadius()+c.getRadius()));
    

    private void validatePoints()
    
        validateDistance(center, x, radius);
        validateDistance(center, z, radius);
    

    private static void validateDistance(Point2D p0, Point2D p1, double d)
    
        double dx = p1.getX() - p0.getX();
        double dy = p1.getY() - p0.getY();
        double distance = Math.sqrt(dx * dx + dy * dy);
        dx /= distance;
        dy /= distance;
        p1.setLocation(p0.getX() + d * dx, p0.getY() + d * dy);
    

    @Override
    public void mouseDragged(MouseEvent e)
    
        if (draggedPoint != null)
        
            draggedPoint.setLocation(e.getPoint());
            validatePoints();
            repaint();
        
    

    @Override
    public void mouseMoved(MouseEvent e)
    
    

    @Override
    public void mouseClicked(MouseEvent e)
    
    

    @Override
    public void mousePressed(MouseEvent e)
    
        draggedPoint = null;
        double thresholdSquared = 10*10;
        double minDs = Double.MAX_VALUE;
        for (Point2D point : points)
        
            double ds = point.distanceSq(e.getPoint());
            if (ds < thresholdSquared && ds < minDs)
            
                minDs = ds;
                draggedPoint = point;
            
        
    

    @Override
    public void mouseReleased(MouseEvent e)
    
        draggedPoint = null;
    

    @Override
    public void mouseEntered(MouseEvent e)
    
    

    @Override
    public void mouseExited(MouseEvent e)
    
    

    static Circle computeCircumcircle(
        double x0, double y0, 
        double x1, double y1, 
        double x2, double y2,
        Circle circle)
    
        // As described on http://mathworld.wolfram.com/Circumcircle.html
        double a = 
            x0 * (y1 - y2) - 
            x1 * (y0 - y2) + 
            x2 * (y0 - y1);
        double m00 = x0 * x0 + y0 * y0;
        double m10 = x1 * x1 + y1 * y1;
        double m20 = x2 * x2 + y2 * y2;
        double bx = 
            -(m00 * (y1 - y2) - 
              m10 * (y0 - y2) + 
              m20 * (y0 - y1));
        double by = 
              m00 * (x1 - x2) - 
              m10 * (x0 - x2) + 
              m20 * (x0 - x1);
        double c = 
            -(m00 * (y2 * x1 - x2 * y1) 
            - m10 * (y2 * x0 - x2 * y0) +
              m20 * (y1 * x0 - x1 * y0));
        double centerX = -bx * 0.5 / a;
        double centerY = -by * 0.5 / a;
        double radius =
            Math.sqrt(bx * bx + by * by - 4 * a * c) * 0.5 / Math.abs(a);
        if (circle == null)
        
            return new Circle(new Point2D.Double(centerX, centerY), radius);
        
        circle.setCenter(centerX, centerY);
        circle.setRadius(radius);
        return circle;
    

    static class Circle
    
        private final Point2D center;
        private double radius;

        Circle()
        
            this.center = new Point2D.Double();
            this.radius = 0.0;
        

        Circle(Point2D center, double radius)
        
            this.center = center;
            this.radius = radius;
        

        Point2D getCenter()
        
            return center;
        
        double getX()
        
            return center.getX();
        
        double getY()
        
            return center.getY();
        
        void setCenter(double x, double y)
        
            center.setLocation(x, y);
        
        double getRadius()
        
            return radius;
        
        void setRadius(double radius)
        
            this.radius = radius;
        
        boolean contains(Point2D p)
        
            return contains(p.getX(), p.getY());
        
        boolean contains(double x, double y)
        
            if (Double.isInfinite(radius))
            
                return true;
            
            double dx = center.getX() - x;
            double dy = center.getY() - y;
            return dx * dx + dy * dy <= radius * radius;
        

        @Override
        public String toString()
        
            return "Circle[("+getX()+","+getY()+"),radius="+radius+"]";
        

    

    private static Line2D rotate(
        double angleRad, Line2D lineSrc, Line2D lineDst)
    
        double x0 = lineSrc.getX1();
        double y0 = lineSrc.getY1();
        double x1 = lineSrc.getX2();
        double y1 = lineSrc.getY2();
        double dx = x1 - x0;
        double dy = y1 - y0;
        double sa = Math.sin(angleRad);
        double ca = Math.cos(angleRad);
        double nx = ca * dx - sa * dy;
        double ny = sa * dx + ca * dy;
        if (lineDst == null)
        
            lineDst = new Line2D.Double();
        
        lineDst.setLine(x0, y0, x0+nx, y0+ny);
        return lineDst;
        

    private static double angle(Line2D line0, Line2D line1)
    
        return normalizeAngle(angleToX(line1) - angleToX(line0));
    

    private static double angle(
        Point2D s0, Point2D e0, Point2D s1, Point2D e1)
    
        return normalizeAngle(angleToX(s1, e1) - angleToX(s0, e0));
    

    private static double angleToX(Line2D line)
    
        return angleToX(
            line.getX1(), line.getY1(), 
            line.getX2(), line.getY2());
    

    private static double angleToX(
        Point2D p0, Point2D p1)
    
        return angleToX(
            p0.getX(), p0.getY(), 
            p1.getX(), p1.getY());
    

    private static double angleToX(
        double x0, double y0, double x1, double y1)
    
        double dx = x1 - x0;
        double dy = y1 - y0;
        double angleRad = Math.atan2(dy, dx); 
        return angleRad;
    

    static double normalizeAngle(double angle)
    
        return (angle + Math.PI + Math.PI) % (Math.PI + Math.PI);        
    



Aquí una forma de resolver su problema: en la figura adjunta puede calcular el ángulo theta en el triángulo rectángulo $ triangle XX'O $ que es la mitad del triángulo isósceles $ triangle XOY $ con ángulo $ ángulo XOY = 2 alpha lt 60 ^ circ $.

Cada valor del segmento $ overline OA = a $ donde $ 0 lt overline OA lt R cos ( alpha) $ determina tanto el ángulo $ theta $ como el radio "pequeño" $ r $ . Tienes $$ begin cases r = sqrt R ^ 2 + a ^ 2-2aR cos ( alpha) \ theta = arcsin left ( dfrac R sin ( alpha) r right) end cases qquad

$$
Finalmente, su ecuación es $$ 2r  theta = R $$ que es $$ 2  sqrt R ^ 2 + a ^ 2-2aR  cos ( alpha)  arcsin  left ( dfrac R  sin ( alpha ) r  right) = R  qquad (**) $$ Debes poner en $ (**) $ el valor de $ r $ dado en $

$, por supuesto. Finalmente tiene una ecuación en una variable $ a $ ya que $ R $ y $ alpha $ son datos del problema.

ingrese la descripción de la imagen aquí

Te mostramos las reseñas y valoraciones de los lectores

Si entiendes que te ha sido útil nuestro artículo, te agradeceríamos que lo compartas con el resto juniors de esta forma nos ayudas a difundir este contenido.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *