9
$\begingroup$

I am strictly an amateur, not a professional mathematician or some such.

This question occurred to me while considering the fact that an angle of 1 radian centered on the center of a circle will produce a circumcircular arc on the circle of the same length as the circle's radius, whereas two segments (AB and BC) of equal length intersecting at 60 degrees will, of course, define a third segment of equal length (between A and C).


To elaborate:

  1. Define a circle C with centerpoint O and radius 'r'.
  2. Define two points, X and Z, on circle C.
  3. Define the lines OX and OZ.
  4. Define angle XOZ.
  5. Define the line OA bisecting XOZ.
  6. Define some point Y on OA such that the circumcircular arc XYZ is of length r.

Point 6, of course, is the one which I do not know how to do. It has occurred to me that this problem is, of course, restricted to cases in which angle XOZ is of fewer than 60 degrees (as at 60 degrees, XYZ becomes a line segment, and above 60 degrees, no arc XYZ of length <= r can exist.

It has also occurred to me that this problem could also be solved by defining some point P on OA such that a circle D with centerpoint P and which runs through X (and Z) exists, where the length of the arc XZ on circle D is r, but I also have no idea how to do that.

Diagram

enter image description here

EDIT: A related question of interest would be to define the function which describes the length of the line OY relative to the length of OX or OZ (ie: 'r'), and the angle of XOZ. There would, naturally, be two valid values of OY, as indicated by @RossMillikan, one for a Y inside the circle, and one for a Y outside the circle.

$\endgroup$
  • $\begingroup$ The world needs "amateurs" like you because many people take pride in hating mathematics. $\endgroup$ – Piquito May 30 '18 at 15:27
  • $\begingroup$ @Piquito well, I am a software developer. It is a related field, in that both rely on strictly logical thinking. $\endgroup$ – MTL-VRN May 30 '18 at 15:31
  • $\begingroup$ Interesting job. I know writers and artists who love mathematics but most of them do not. Unfortunately, it must be said, some of those who claim to be lovers of mathematics are actually snobbish. $\endgroup$ – Piquito May 30 '18 at 15:45
  • $\begingroup$ But this is a trivial problem, unless you've not articulated your problem well. The circle whose arc is $r$ and passing through the specified points is none other than the one you started with, for if you suppose there is some other such circle, then it must needs have the same radius as the one you started with, differing at most only by some set of euclidean transformations. $\endgroup$ – Allawonder May 30 '18 at 16:04
  • $\begingroup$ @Allawonder What do you mean? The circle defining the arc is only the same as the original circle when the angle of XOZ is exactly 1 radian. Heck, just look at the diagram in the question; the length of arc XZ on circle C appears to be less than the length of OX. Furthermore, even if the diagram had been constructed such that the length of arc XZ was equal to the length of OX, if the angle of XOZ was then reduced, the length of arc XZ would reduce as well, while OX remained constant. Similarly, if angle XOZ increased, so too would the length of arc XZ, and OX would still remain constant. $\endgroup$ – MTL-VRN May 30 '18 at 16:16
2
$\begingroup$

Here a way to solve your problem: in the attached figure you can calculate the theta angle in the right triangle $\triangle{XX'O}$ which is the half of the isosceles triangle $\triangle{XOY}$ with angle $\angle{XOY}=2\alpha\lt 60^{\circ}$.

Each value of the segment $\overline{OA}=a$ where $0\lt \overline{OA}\lt R\cos(\alpha)$ determines both the angle $\theta$ and the "little" radius $r$. You have $$\begin{cases}r=\sqrt{R^2+a^2-2aR\cos(\alpha)}\\\theta=\arcsin\left(\dfrac{R\sin(\alpha)}{r}\right)\end{cases}\qquad(*)$$

Finally your equation is $$2r\theta=R$$ that is $$2\sqrt{R^2+a^2-2aR\cos(\alpha)}\arcsin\left(\dfrac{R\sin(\alpha)}{r}\right)=R\qquad(**)$$ You must put in $(**)$ the value of $r$ given in $(*)$, of course. You finally have an equation in one variable $a$ since $R$ and $\alpha$ are data of the problem. enter image description here

$\endgroup$
2
$\begingroup$

Point $Y$ will exist. There will be two points that satisfy the requirement, one on each side of $XZ$. You can prove that using the intermediate value theorem. The segment $XZ$ is too short and the arc with a proposed $Y$ far away will be too long, so there is a point in between that is just right. I am sure it will generally not be constructible with compass and straightedge but I don't know an easy way to show that.

$\endgroup$
2
$\begingroup$

This is certainly not an acceptable answer. But maybe a useful contribution. I just hacked down a small program where you can drag around the x/z points, and it prints some of the relevant information.

Particularly, it prints the angle between OX and OZ, and the relative length of the line OY (referring to the radius).

enter image description here

As you already noted, the solution can only exist for an angle that is not greater than 60°. (For 60°, the result will just be the original circle). In this case, the distance of Y to O will be 1.0 (relative to the radius!).

The lower limit for the angle seems to be about 37°, and the relative distance of Y to O will then be about 1.26. But of course, this computation only gives a rough approximation!

The implementation is here, in Java. It should be standalone, and can be compiled and started directly in any IDE.

But note: The implementation is really crude, so take it with a grain of salt. Particularly, it does a "brute force" search for the distance of Y at which the resulting arc length will be approximately equal to the radius. This could or should be improved in many ways, e.g. doing a binary search, and/or searching for both solutions that are supposed to exist at each point.

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<Point2D> 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<Point2D>();
        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<n+n; i++)
        {
            double alpha = (double)i / n;

            Point2D y = new Point2D.Double(bisector.getX2(), bisector.getY2());
            double distance = alpha * radius;
            validateDistance(center, y, distance);

            Circle c = computeCircumcircle(
                x.getX(), x.getY(),
                y.getX(), y.getY(),
                z.getX(), z.getY(), null);

            double arcLength = computeArcLength(c.getCenter(), x, z);
            double deviation = Math.abs(arcLength - radius);
            if (deviation < minDeviation && deviation < 0.1)
            {
                double distanceToCenter = center.distance(y);
                if (distance < minDistanceToCenter)
                {
                    minDistanceToCenter = distanceToCenter;
                    minDeviation = deviation;
                    closestY = y;
                }
            }
        }
        return closestY;
    }


    private static double computeArcLength(Point2D c, Point2D a, Point2D b)
    {
        // Based on https://math.stackexchange.com/a/830630/133498
        double d = a.distance(b);
        double r = c.distance(a);
        double theta = Math.acos(1 - ((d * d) / (2 * r * r)));
        double length = r * theta;
        return length;
    }


    private static Line2D computeBisector(Point2D c, Point2D p0, Point2D p1)
    {
        Line2D line0 = new Line2D.Double(c, p0);
        Line2D line1 = new Line2D.Double(c, p1);
        double angleRad = angle(line0, line1);
        return rotate(-angleRad * 0.5, line1, null);
    }


    static void drawPoints(Graphics2D g, List<Point2D> 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);        
    }


}
$\endgroup$
  • $\begingroup$ Well, as I mentioned, I am also a software developer, so I love something that I can sink my teeth into from a professional angle. However, I noticed one problem right away in your description, at least. The result is the original circle at 1 radian (~57.29 degrees), not 60 degrees. This appears to match your animation. By contrast, at 60 degrees, the resulting circle does not exist, as a straight line between X and Z is of the necessary length (XOZ is an equilateral triangle when the angle of XOZ is 60 degrees). $\endgroup$ – MTL-VRN May 30 '18 at 17:17
  • $\begingroup$ Again, these are approximations, and there always the nasty stability issues. I cannot stress enough that this was a quick hack, in order to "play around" and observe the behavior a bit. There are some constants, like radius=200, n=1000, deviation<0.1. Fiddling with this to radius=10, n=10000, deviation<1.0 will cause the result to be printed at ~60°. (If desired, I could try to make the computations more robust but would have to see how to allocate some time for that...) $\endgroup$ – Marco13 May 30 '18 at 17:40
1
$\begingroup$

AS noted by Ross Millikan the searched point will exist.

I suggest a way to find it. I use figure with different names:

enter image description here

where we know:

$\overline{AC}=\overline{AB}=r$

$\angle CAE=\angle CAD=\gamma$

and we search:

$\angle CED=\theta $

$\angle ACE=\varphi$

so that we have $$ \theta=\gamma+ \varphi \qquad (1) $$

with: $\overline{CE}=x\quad$ and $\quad \overline{AE}=y$

using the low of cosines for the triangle $ACE$ we have $$ y^2=r^2+x^2-2rx\cos \varphi \qquad (2) $$ and, using the triangles $ACD$ and $CED$: $$ r^2+(y+x)^2-2r(y+x)\cos \gamma = 2x^2-2x^2\cos \theta \qquad (3) $$

and, with the equation that gives the arc $CDB=r$: $$ 2x\theta=r \qquad (4) $$ we have four equations for the four unknowns.

The system is not simple to solve, and maybe that it can be simplified with a different choice of the unknowns.

$\endgroup$
0
$\begingroup$

Preface. It took me some time to understand the question, so pardon my initial idiocy. I find that it is somewhat interesting. Here's a report of what I did.

Refer to the figure in OP. We want the arc $XYZ$ whose length is equal to $r$. As OP said, it is meaningless to seek this for $X\hat O Z=\theta\ge π/3$. Now it is easy to see that it is sufficient to find the radius $s$ of the sought arc with length $x$, for once we know this we can always find the centre from the constraints that the arc must pass through $X$ and $Z$ and centered somewhere on the line $OA$. Since we always have two such arcs (forming a complete circle), we choose the smaller one, and it is the one whose length we denote by $x$. The possible radii $s$ of these arcs must satisfy $s\ge c$, where $c$ is half of the chord $XZ$. Now for each such $s$ we always have two such arcs (counting multiplicities), but we consider them to be one (that is, we consider the congruence class of the arcs instead of individuals, with exactly two per class) since we are only interested in their lengths, which must be equal since they are congruent. Furthermore, we seek such $s$ as make $x=1$ for fixed $\theta\in(0,π/3)$.

Since for each $r\ge c$, we have one and only one value for $x$, we can form a function $x(s)$ and simply investigate the $s$ that solve $x=1$. This dissolves the problem for some positive $\theta<π/3$.

By considering the figure we can see immediately that $x$ must satisfy the following:

  1. The function $x(s)$ is continuous.

  2. It decreases strictly with increasing $r$.

  3. At $s=c=r\sin{\theta/2}$, the minimum in the domain, we have $x(c)=πc$.

  4. When $s=r$, we have that $x(r)=\theta$ whenever $\theta$ satisfies the constraints imposed on it.

  5. The graph of $x$ intercepts both axes nowhere.

  6. As $r\to\infty$, $x\to 2c$.

  7. Consequently (specifically by 2 and 5), $x$ is bounded.

We can now imagine, for $\theta=1$ and $r=1$, for example, that the graph of $x$ looks like a segment (namely from about $r=1/2$ to $\infty$) of the graph of $e^{-s}$ translated upwards.

From now on, we shall take $r=1$ since we must needs have a unit. If we consider the diagram and make some simple constructions, we will see that $x=s\phi$, where $\phi$ is the angle of the arc which we seek, subtended at its centre $P$. Note that $\phi$ decreases from $π$ to $0$ with increasing $r$. To find a relationship between $s$ and $\phi$ is easy. Let $P$ be the centre of the arc $XYZ$, then we consider the triangle $PXQ$, where $Q$ is the point where the chord $XZ$ and the line $OA$ intersect. From this we see that $s\sin\phi/2=c=r\sin\theta/2=\sin\theta/2$. Substituting in the previous relation and doing a little rearrangement gives $$x(s)=2s\arcsin\left(\frac 1s \sin\frac \theta2\right)$$ for $s\ge\sin(\theta/2)$ and fixed $\theta$. Indeed if we choose $\theta=1$ and set $x=1$, we find the only solution to be $s=1$, as expected. For any fixed $\theta$, it is easy to see that there is exactly one solution since the constant function $1$ must intersect $x$ at most once, being strictly decreasing.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.