Ejemplo n.º 1
0
        //Demonstrates: congruent chords have congruent arcs

        public Page306Theorem7_4_1_Semicircle(bool onoff, bool complete) : base(onoff, complete)
        {
            Point o = new Point("O", 0, 0); points.Add(o);
            Point c = new Point("C", 15, 0); points.Add(c);

            Point s = new Point("S", -3, -4); points.Add(s);
            Point t = new Point("T", 3, 4); points.Add(t);
            Point u = new Point("U", 2, Math.Sqrt(21)); points.Add(u);

            Point a = new Point("A", 12, 4); points.Add(a);
            Point b = new Point("B", 18, -4); points.Add(b);
            Point d = new Point("D", 16, -Math.Sqrt(24)); points.Add(d);

            Segment st = new Segment(s, t); segments.Add(st);
            Segment ab = new Segment(a, b); segments.Add(ab);
            Segment ou = new Segment(o, u); segments.Add(ou);
            Segment cd = new Segment(c, d); segments.Add(cd);

            Circle c1 = new Circle(o, 5.0);
            Circle c2 = new Circle(c, 5.0);

            circles.Add(c1);
            circles.Add(c2);

            parser = new LiveGeometry.TutorParser.HardCodedParserMain(points, collinear, segments, circles, onoff);

            given.Add(new GeometricCongruentSegments(st, ab));

            Semicircle semi1 = (Semicircle)parser.Get(new Semicircle(c1, s, t, u, st));
            Semicircle semi2 = (Semicircle)parser.Get(new Semicircle(c2, a, b, d, ab));

            goals.Add(new GeometricCongruentArcs(semi1, semi2));
        }
Ejemplo n.º 2
0
        //
        //     C
        //     |\
        //     | \
        //     |  \
        //     |   O
        //     |    \
        //     |_    \
        //   A |_|____\ B
        //
        // SemiCircle(O, BC), Angle(BAC) -> RightAngle(BAC)
        //
        public static List <EdgeAggregator> InstantiateTheorem(Semicircle semi, Angle angle, GroundedClause original)
        {
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            // The angle needs to be inscribed in the given semicircle

            // Note: Previously this was checked indirectly by verifying that the angle intercepts a semicircle, but since semicircles now
            // require 3 points to be defined, it is safer to directly verify that the angle is inscribed in the semicircle.
            // (There may not have been any points defined on the other side of the diameter,
            // meaning there would not actually be any defined semicircles which the angle intercepts).

            if (!semi.AngleIsInscribed(angle))
            {
                return(newGrounded);
            }

            Strengthened newRight = new Strengthened(angle, new RightAngle(angle));

            // For hypergraph
            List <GroundedClause> antecedent = new List <GroundedClause>();

            antecedent.Add(original);
            antecedent.Add(angle);

            newGrounded.Add(new EdgeAggregator(antecedent, newRight, annotation));

            return(newGrounded);
        }
Ejemplo n.º 3
0
    // Construct the region between a circle and circle:
    //     __
    //    ( (
    //   ( (
    //  ( (
    //   ( (
    //    ( (
    //     --
    private Atomizer.AtomicRegion ConstructBasicCircleCircleRegion(Segment chord, Circle smaller, Circle larger)
    {
        AtomicRegion region = new AtomicRegion();

        Arc arc1 = null;

        if (smaller.DefinesDiameter(chord))
        {
            Point midpt = smaller.Midpoint(chord.Point1, chord.Point2, larger.Midpoint(chord.Point1, chord.Point2));

            arc1 = new Semicircle(smaller, chord.Point1, chord.Point2, midpt, chord);
        }
        else
        {
            arc1 = new MinorArc(smaller, chord.Point1, chord.Point2);
        }

        MinorArc arc2 = new MinorArc(larger, chord.Point1, chord.Point2);

        region.AddConnection(chord.Point1, chord.Point2, ConnectionType.ARC, arc1);

        region.AddConnection(chord.Point1, chord.Point2, ConnectionType.ARC, arc2);

        return(region);
    }
Ejemplo n.º 4
0
        //
        // If one of the endpoints of that is inside of this; and vice versa.
        //
        public bool Overlap(Connection that)
        {
            if (that.type != this.type)
            {
                return(false);
            }

            if (this.type == ConnectionType.ARC)
            {
                if (!(this.segmentOrArc as Arc).StructurallyEquals(this.segmentOrArc as Arc))
                {
                    return(false);
                }

                // If the arcs just touch, it's not overlap.
                if (this.segmentOrArc is MinorArc)
                {
                    MinorArc minor = this.segmentOrArc as MinorArc;
                    if (minor.PointLiesStrictlyOn(that.endpoint1) || minor.PointLiesStrictlyOn(that.endpoint2))
                    {
                        return(true);
                    }
                }
                else if (this.segmentOrArc is Semicircle)
                {
                    Semicircle semi = this.segmentOrArc as Semicircle;
                    if (semi.PointLiesStrictlyOn(that.endpoint1) || semi.PointLiesStrictlyOn(that.endpoint2))
                    {
                        return(true);
                    }
                }
                else if (this.segmentOrArc is MajorArc)
                {
                    MajorArc major = this.segmentOrArc as MajorArc;
                    if (major.PointLiesStrictlyOn(that.endpoint1) || major.PointLiesStrictlyOn(that.endpoint2))
                    {
                        return(true);
                    }
                }
                return(false);
            }
            else if (this.type == ConnectionType.SEGMENT)
            {
                Segment thisSegment = this.segmentOrArc as Segment;
                Segment thatSegment = that.segmentOrArc as Segment;

                if (!thisSegment.IsCollinearWith(thatSegment))
                {
                    return(false);
                }

                return(thisSegment.CoincidingWithOverlap(thatSegment));
            }

            return(false);
        }
Ejemplo n.º 5
0
        private List <Atomizer.AtomicRegion> ConvertToSemicircle(Segment diameter, Semicircle semi)
        {
            // Verification Step 2.
            if (!diameter.PointLiesOnAndExactlyBetweenEndpoints(semi.theCircle.center))
            {
                throw new Exception("Semicircle: expected center between endpoints.");
            }

            Sector sector = new Sector(semi);

            return(Utilities.MakeList <AtomicRegion>(new ShapeAtomicRegion(sector)));
        }
        private Semicircle CreateImpliedSemicircle(Circle circle, Segment diameter, Point oppositePnt)
        {
            Point midpt = circle.Midpoint(diameter.Point1, diameter.Point2);
            //Create semicircles from the midpt and the given oppositePnt, make sure they do not form the same side
            Semicircle semi1 = new Semicircle(circle, diameter.Point1, diameter.Point2, midpt, diameter);

            if (semi1.SameSideSemicircle(new Semicircle(circle, diameter.Point1, diameter.Point2, oppositePnt, diameter)))
            {
                semi1 = new Semicircle(circle, diameter.Point1, diameter.Point2, circle.OppositePoint(midpt), diameter);
            }
            return(semi1);
        }
Ejemplo n.º 7
0
        //
        //     C
        //     |\
        //     | \
        //     |  \
        //     |   O
        //     |    \
        //     |_    \
        //   A |_|____\ B
        //
        // SemiCircle(O, BC), Angle(BAC) -> RightAngle(BAC)
        //
        public static List <EdgeAggregator> Instantiate(GroundedClause clause)
        {
            annotation.active = EngineUIBridge.JustificationSwitch.ANGLE_INSCRIBED_SEMICIRCLE_IS_RIGHT;

            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            if (clause is Angle)
            {
                Angle angle = clause as Angle;

                foreach (Semicircle semi in candidateSemiCircles)
                {
                    newGrounded.AddRange(InstantiateTheorem(semi, angle, semi));
                }

                foreach (Strengthened streng in candidateStrengthened)
                {
                    newGrounded.AddRange(InstantiateTheorem(streng.strengthened as Semicircle, angle, streng));
                }

                candidateInscribed.Add(angle);
            }
            else if (clause is Semicircle)
            {
                Semicircle semi = clause as Semicircle;

                foreach (Angle angle in candidateInscribed)
                {
                    newGrounded.AddRange(InstantiateTheorem(semi, angle, semi));
                }

                candidateSemiCircles.Add(semi);
            }

            else if (clause is Strengthened)
            {
                Strengthened streng = clause as Strengthened;

                if (!(streng.strengthened is Semicircle))
                {
                    return(newGrounded);
                }

                foreach (Angle angle in candidateInscribed)
                {
                    newGrounded.AddRange(InstantiateTheorem(streng.strengthened as Semicircle, angle, streng));
                }

                candidateStrengthened.Add(streng);
            }

            return(newGrounded);
        }
        private void AddSemicircleClauses(Semicircle semi)
        {
            if (!GeometryTutorLib.Utilities.HasStructurally <Semicircle>(semiCircles, semi))
            {
                semiCircles.Add(semi);
                semicircleSectors.Add(new Sector(semi));
            }

            //Add arcInMiddle
            //For semicircles, only considering the defining middle point as an inMiddle point
            //This is to avoid arc equations such as MinorArc(RX) + MinorArc(XT) = Semicircle(RST), which might not make sense to a user
            GeometryTutorLib.Utilities.AddStructurallyUnique <ArcInMiddle>(arcInMiddle, new ArcInMiddle(semi.middlePoint, semi));
        }
Ejemplo n.º 9
0
    // Construct the region between a chord and the circle arc:
    //    (|
    //   ( |
    //  (  |
    //   ( |
    //    (|
    //
    private List <AtomicRegion> ConstructBasicLineCircleRegion(Segment chord, Circle circle)
    {
        //
        // Standard
        //
        if (!circle.DefinesDiameter(chord))
        {
            AtomicRegion region = new AtomicRegion();

            Arc theArc = new MinorArc(circle, chord.Point1, chord.Point2);

            region.AddConnection(chord.Point1, chord.Point2, ConnectionType.ARC, theArc);

            region.AddConnection(chord.Point1, chord.Point2, ConnectionType.SEGMENT, chord);

            return(Utilities.MakeList <AtomicRegion>(region));
        }

        //
        // Semi-circles
        //

        Point             midpt   = circle.Midpoint(chord.Point1, chord.Point2);
        Arc               semi1   = new Semicircle(circle, chord.Point1, chord.Point2, midpt, chord);
        ShapeAtomicRegion region1 = new ShapeAtomicRegion(new Sector(semi1));

        Point             opp     = circle.OppositePoint(midpt);
        Arc               semi2   = new Semicircle(circle, chord.Point1, chord.Point2, opp, chord);
        ShapeAtomicRegion region2 = new ShapeAtomicRegion(new Sector(semi2));

        List <AtomicRegion> regions = new List <AtomicRegion>();

        regions.Add(region1);
        regions.Add(region2);

        return(regions);
    }
Ejemplo n.º 10
0
        private List <Atomizer.AtomicRegion> MixedArcChordedRegion(List <Circle> thatCircles, UndirectedPlanarGraph.PlanarGraph graph)
        {
            List <AtomicRegion> regions = new List <AtomicRegion>();

            // Every segment may be have a set of circles. (on each side) surrounding it.
            // Keep parallel lists of: (1) segments, (2) (real) arcs, (3) left outer circles, and (4) right outer circles
            Segment[] regionsSegments   = new Segment[points.Count];
            Arc[]     arcSegments       = new Arc[points.Count];
            Circle[]  leftOuterCircles  = new Circle[points.Count];
            Circle[]  rightOuterCircles = new Circle[points.Count];

            //
            // Populate the parallel arrays.
            //
            int currCounter = 0;

            for (int p = 0; p < points.Count;)
            {
                UndirectedPlanarGraph.PlanarGraphEdge edge = graph.GetEdge(points[p], points[(p + 1) % points.Count]);
                Segment currSegment = new Segment(points[p], points[(p + 1) % points.Count]);

                //
                // If a known segment, seek a sequence of collinear segments.
                //
                if (edge.edgeType == UndirectedPlanarGraph.EdgeType.REAL_SEGMENT)
                {
                    Segment actualSeg = currSegment;

                    bool collinearExists = false;
                    int  prevPtIndex;
                    for (prevPtIndex = p + 1; prevPtIndex < points.Count; prevPtIndex++)
                    {
                        // Make another segment with the next point.
                        Segment nextSeg = new Segment(points[p], points[(prevPtIndex + 1) % points.Count]);

                        // CTA: This criteria seems invalid in some cases....; may not have collinearity

                        // We hit the end of the line of collinear segments.
                        if (!currSegment.IsCollinearWith(nextSeg))
                        {
                            break;
                        }

                        collinearExists = true;
                        actualSeg       = nextSeg;
                    }

                    // If there exists an arc over the actual segment, we have an embedded circle to consider.
                    regionsSegments[currCounter] = actualSeg;

                    if (collinearExists)
                    {
                        UndirectedPlanarGraph.PlanarGraphEdge collEdge = graph.GetEdge(actualSeg.Point1, actualSeg.Point2);
                        if (collEdge != null)
                        {
                            if (collEdge.edgeType == UndirectedPlanarGraph.EdgeType.REAL_ARC)
                            {
                                // Find all applicable circles
                                List <Circle> circles = GetAllApplicableCircles(thatCircles, actualSeg.Point1, actualSeg.Point2);

                                // Get the exact outer circles for this segment (and create any embedded regions).
                                regions.AddRange(ConvertToCircleCircle(actualSeg, circles, out leftOuterCircles[currCounter], out rightOuterCircles[currCounter]));
                            }
                        }
                    }

                    currCounter++;
                    p = prevPtIndex;
                }
                else if (edge.edgeType == UndirectedPlanarGraph.EdgeType.REAL_DUAL)
                {
                    regionsSegments[currCounter] = new Segment(points[p], points[(p + 1) % points.Count]);

                    // Get the exact chord and set of circles
                    Segment chord = regionsSegments[currCounter];

                    // Find all applicable circles
                    List <Circle> circles = GetAllApplicableCircles(thatCircles, points[p], points[(p + 1) % points.Count]);

                    // Get the exact outer circles for this segment (and create any embedded regions).
                    regions.AddRange(ConvertToCircleCircle(chord, circles, out leftOuterCircles[currCounter], out rightOuterCircles[currCounter]));

                    currCounter++;
                    p++;
                }
                else if (edge.edgeType == UndirectedPlanarGraph.EdgeType.REAL_ARC)
                {
                    //
                    // Find the unique circle that contains these two points.
                    // (if more than one circle has these points, we would have had more intersections and it would be a direct chorded region)
                    //
                    List <Circle> circles = GetAllApplicableCircles(thatCircles, points[p], points[(p + 1) % points.Count]);

                    if (circles.Count != 1)
                    {
                        throw new Exception("Need ONLY 1 circle for REAL_ARC atom id; found (" + circles.Count + ")");
                    }

                    arcSegments[currCounter++] = new MinorArc(circles[0], points[p], points[(p + 1) % points.Count]);

                    p++;
                }
            }

            //
            // Check to see if this is a region in which some connections are segments and some are arcs.
            // This means there were no REAL_DUAL edges.
            //
            List <AtomicRegion> generalRegions = GeneralAtomicRegion(regionsSegments, arcSegments);

            if (generalRegions.Any())
            {
                return(generalRegions);
            }

            // Copy the segments into a list (ensuring no nulls)
            List <Segment> actSegments = new List <Segment>();

            foreach (Segment side in regionsSegments)
            {
                if (side != null)
                {
                    actSegments.Add(side);
                }
            }

            // Construct a polygon out of the straight-up segments
            // This might be a polygon that defines a pathological region.
            Polygon poly = Polygon.MakePolygon(actSegments);

            // Determine which outermost circles apply inside of this polygon.
            Circle[] circlesCutInsidePoly = new Circle[actSegments.Count];
            for (int p = 0; p < actSegments.Count; p++)
            {
                if (leftOuterCircles[p] != null && rightOuterCircles[p] == null)
                {
                    circlesCutInsidePoly[p] = CheckCircleCutInsidePolygon(poly, leftOuterCircles[p], actSegments[p].Point1, actSegments[p].Point2);
                }
                else if (leftOuterCircles[p] == null && rightOuterCircles[p] != null)
                {
                    circlesCutInsidePoly[p] = CheckCircleCutInsidePolygon(poly, rightOuterCircles[p], actSegments[p].Point1, actSegments[p].Point2);
                }
                else if (leftOuterCircles[p] != null && rightOuterCircles[p] != null)
                {
                    circlesCutInsidePoly[p] = CheckCircleCutInsidePolygon(poly, leftOuterCircles[p], actSegments[p].Point1, actSegments[p].Point2);

                    if (circlesCutInsidePoly[p] == null)
                    {
                        circlesCutInsidePoly[p] = rightOuterCircles[p];
                    }
                }
                else
                {
                    circlesCutInsidePoly[p] = null;
                }
            }

            bool isStrictPoly = true;

            for (int p = 0; p < actSegments.Count; p++)
            {
                if (circlesCutInsidePoly[p] != null || arcSegments[p] != null)
                {
                    isStrictPoly = false;
                    break;
                }
            }

            // This is just a normal shape region: polygon.
            if (isStrictPoly)
            {
                regions.Add(new ShapeAtomicRegion(poly));
            }
            // A circle cuts into the polygon.
            else
            {
                //
                // Now that all interior arcs have been identified, construct the atomic (probably pathological) region
                //
                AtomicRegion pathological = new AtomicRegion();
                for (int p = 0; p < actSegments.Count; p++)
                {
                    //
                    // A circle cutting inside the polygon
                    //
                    if (circlesCutInsidePoly[p] != null)
                    {
                        Arc theArc = null;

                        if (circlesCutInsidePoly[p].DefinesDiameter(regionsSegments[p]))
                        {
                            Point midpt = circlesCutInsidePoly[p].Midpoint(regionsSegments[p].Point1, regionsSegments[p].Point2);

                            if (!poly.IsInPolygon(midpt))
                            {
                                midpt = circlesCutInsidePoly[p].OppositePoint(midpt);
                            }

                            theArc = new Semicircle(circlesCutInsidePoly[p], regionsSegments[p].Point1, regionsSegments[p].Point2, midpt, regionsSegments[p]);
                        }
                        else
                        {
                            theArc = new MinorArc(circlesCutInsidePoly[p], regionsSegments[p].Point1, regionsSegments[p].Point2);
                        }

                        pathological.AddConnection(regionsSegments[p].Point1, regionsSegments[p].Point2, ConnectionType.ARC, theArc);
                    }
                    //
                    else
                    {
                        // We have a direct arc
                        if (arcSegments[p] != null)
                        {
                            pathological.AddConnection(regionsSegments[p].Point1, regionsSegments[p].Point2,
                                                       ConnectionType.ARC, arcSegments[p]);
                        }
                        // Use the segment
                        else
                        {
                            pathological.AddConnection(regionsSegments[p].Point1, regionsSegments[p].Point2,
                                                       ConnectionType.SEGMENT, regionsSegments[p]);
                        }
                    }
                }

                regions.Add(pathological);
            }


            return(regions);
        }
        //
        // Detect diameters and generate all of the Semicircle Arc and ArcInMiddle clauses
        //
        private void GenerateSemicircleClauses(Circle circle)
        {
            if (circle.pointsOnCircle.Count == 2)
            {
                Segment diameter = new Segment(circle.pointsOnCircle[0], circle.pointsOnCircle[1]);

                if (circle.DefinesDiameter(diameter))
                {
                    Point midpt = circle.Midpoint(diameter.Point1, diameter.Point2);
                    Point opp   = circle.OppositePoint(midpt);

                    AddSemicircleClauses(new Semicircle(circle, diameter.Point1, diameter.Point2, midpt, diameter));
                    AddSemicircleClauses(new Semicircle(circle, diameter.Point1, diameter.Point2, opp, diameter));
                }
            }

            for (int p1 = 0; p1 < circle.pointsOnCircle.Count - 1; p1++)
            {
                for (int p2 = p1 + 1; p2 < circle.pointsOnCircle.Count; p2++)
                {
                    Segment diameter = new Segment(circle.pointsOnCircle[p1], circle.pointsOnCircle[p2]);

                    if (circle.DefinesDiameter(diameter))
                    {
                        //Get the endpoints of the diameter and the indices of these endpoints
                        Point e1 = diameter.Point1;
                        Point e2 = diameter.Point2;
                        //int p1 = circle.pointsOnCircle.IndexOf(e1);
                        //int p2 = circle.pointsOnCircle.IndexOf(e2);

                        ////For partitioning purposes, order of the endpoints matters. Make sure p1 holds the lower of the two indices
                        //if (p1 > p2)
                        //{
                        //    int p3 = p1;
                        //    p1 = p2;
                        //    p2 = p3;
                        //}

                        // Partition the remaining points on the circle
                        List <Point> minorArcPoints;
                        List <Point> majorArcPoints;
                        PartitionSemiCircleArcPoints(circle.pointsOnCircle, p1, p2, out minorArcPoints, out majorArcPoints);

                        // Semicircle requires 3 points to be defined - the two endpoints and a point inbetween
                        // The minorArcPoints and majorArcPoints lists contain all the potential inbetween points for either side of the diameter
                        // Handle 'side' 1:
                        // If majorArcPoints is empty, create an implied semicircle (minorArcPoints should be guaranteed to have at least one point, since
                        // the case of having only 2 points on the circle was already handled)
                        if (majorArcPoints.Count == 0 && minorArcPoints.Count != 0)
                        {
                            AddSemicircleClauses(CreateImpliedSemicircle(circle, diameter, minorArcPoints[0]));
                        }
                        else
                        {
                            for (int i = 0; i < majorArcPoints.Count; ++i)
                            {
                                Semicircle semi = new Semicircle(circle, e1, e2, majorArcPoints[i], minorArcPoints, majorArcPoints, diameter);
                                AddSemicircleClauses(semi);
                            }
                        }
                        // Handle 'side' 2:
                        if (minorArcPoints.Count == 0 && majorArcPoints.Count != 0)
                        {
                            AddSemicircleClauses(CreateImpliedSemicircle(circle, diameter, majorArcPoints[0]));
                        }
                        else
                        {
                            for (int i = 0; i < minorArcPoints.Count; ++i)
                            {
                                Semicircle semi = new Semicircle(circle, e1, e2, minorArcPoints[i], majorArcPoints, minorArcPoints, diameter);
                                AddSemicircleClauses(semi);
                            }
                        }
                    }
                }
            }
        }
        //
        //          C
        //         /)
        //        /  )
        //       / )
        //      / )
        //   A /)_________ B
        //
        // Tangent(Circle(O), Segment(AB)), Intersection(Segment(AC), Segment(AB)) -> 2 * Angle(CAB) = Arc(C, B)
        //
        public static List <EdgeAggregator> InstantiateTheorem(Intersection inter, Tangent tangent, GroundedClause original)
        {
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            CircleSegmentIntersection tan = tangent.intersection as CircleSegmentIntersection;

            //
            // Does this tangent apply to this intersection?
            //
            if (!inter.intersect.StructurallyEquals(tangent.intersection.intersect))
            {
                return(newGrounded);
            }

            Segment secant     = null;
            Segment tanSegment = null;

            if (tan.HasSegment(inter.lhs))
            {
                secant     = inter.rhs;
                tanSegment = inter.lhs;
            }
            else if (tan.HasSegment(inter.rhs))
            {
                secant     = inter.lhs;
                tanSegment = inter.rhs;
            }
            else
            {
                return(newGrounded);
            }

            //
            // Acquire the angle and intercepted arc.
            //
            Segment chord = tan.theCircle.GetChord(secant);

            if (chord == null)
            {
                return(newGrounded);
            }
            //Segment chord = tan.theCircle.ContainsChord(secant);

            // Arc
            // We want the MINOR ARC only!
            if (tan.theCircle.DefinesDiameter(chord))
            {
                Arc   theArc = null;
                Point midpt  = PointFactory.GeneratePoint(tan.theCircle.Midpoint(chord.Point1, chord.Point2));
                Point opp    = PointFactory.GeneratePoint(tan.theCircle.OppositePoint(midpt));

                Point tanPoint = tanSegment.OtherPoint(inter.intersect);

                if (tanPoint != null)
                {
                    // Angle; the smaller angle is always the chosen angle
                    Angle theAngle = new Angle(chord.OtherPoint(inter.intersect), inter.intersect, tanPoint);

                    theArc = new Semicircle(tan.theCircle, chord.Point1, chord.Point2, midpt, chord);
                    newGrounded.Add(CreateClause(inter, original, theAngle, theArc));

                    theArc = new Semicircle(tan.theCircle, chord.Point1, chord.Point2, opp, chord);
                    newGrounded.Add(CreateClause(inter, original, theAngle, theArc));
                }
                else
                {
                    // Angle; the smaller angle is always the chosen angle
                    Angle theAngle = new Angle(chord.OtherPoint(inter.intersect), inter.intersect, tanSegment.Point1);

                    theArc = new Semicircle(tan.theCircle, chord.Point1, chord.Point2, midpt, chord);
                    newGrounded.Add(CreateClause(inter, original, theAngle, theArc));

                    theArc = new Semicircle(tan.theCircle, chord.Point1, chord.Point2, opp, chord);
                    newGrounded.Add(CreateClause(inter, original, theAngle, theArc));

                    // Angle; the smaller angle is always the chosen angle
                    theAngle = new Angle(chord.OtherPoint(inter.intersect), inter.intersect, tanSegment.Point2);

                    theArc = new Semicircle(tan.theCircle, chord.Point1, chord.Point2, midpt, chord);
                    newGrounded.Add(CreateClause(inter, original, theAngle, theArc));

                    theArc = new Semicircle(tan.theCircle, chord.Point1, chord.Point2, opp, chord);
                    newGrounded.Add(CreateClause(inter, original, theAngle, theArc));
                }
            }
            else
            {
                Arc theArc = new MinorArc(tan.theCircle, chord.Point1, chord.Point2);

                // Angle; the smaller angle is always the chosen angle
                Point endPnt   = (inter.intersect.StructurallyEquals(tanSegment.Point1)) ? tanSegment.Point2 : tanSegment.Point1;
                Angle theAngle = new Angle(chord.OtherPoint(inter.intersect), inter.intersect, endPnt);

                if (theAngle.measure > 90)
                {
                    //If the angle endpoint was already set to Point2, or if the intersect equals Point2, then the smaller angle does not exist
                    //In this case, should we create a major arc or return nothing?
                    if (endPnt.StructurallyEquals(tanSegment.Point2) || inter.intersect.StructurallyEquals(tanSegment.Point2))
                    {
                        return(newGrounded);
                    }
                    theAngle = new Angle(chord.OtherPoint(inter.intersect), inter.intersect, tanSegment.Point2);
                }

                Multiplication            product  = new Multiplication(new NumericValue(2), theAngle);
                GeometricAngleArcEquation angArcEq = new GeometricAngleArcEquation(product, theArc);

                // For hypergraph
                List <GroundedClause> antecedent = new List <GroundedClause>();
                antecedent.Add(original);
                antecedent.Add(inter);
                antecedent.Add(theArc);
                antecedent.Add(theAngle);

                newGrounded.Add(new EdgeAggregator(antecedent, angArcEq, annotation));
            }



            return(newGrounded);
        }