// Path: src/main/java/com/codegame/codeseries/notreal2d/util/GeometryUtil.java
// public final class GeometryUtil {
//     private GeometryUtil() {
//         throw new UnsupportedOperationException();
//     }
// 
//     @Contract(pure = true)
//     public static double normalizeAngle(double angle) {
//         while (angle > PI) {
//             angle -= DOUBLE_PI;
//         }
// 
//         while (angle < -PI) {
//             angle += DOUBLE_PI;
//         }
// 
//         return angle;
//     }
// 
//     @Contract(pure = true)
//     public static boolean isAngleBetween(double angle, double startAngle, double finishAngle) {
//         while (finishAngle < startAngle) {
//             finishAngle += DOUBLE_PI;
//         }
// 
//         while (finishAngle - DOUBLE_PI > startAngle) {
//             finishAngle -= DOUBLE_PI;
//         }
// 
//         while (angle < startAngle) {
//             angle += DOUBLE_PI;
//         }
// 
//         while (angle - DOUBLE_PI > startAngle) {
//             angle -= DOUBLE_PI;
//         }
// 
//         return angle >= startAngle && angle <= finishAngle;
//     }
// 
//     public static boolean isPointInsideConvexPolygon(
//             @Nonnull Point2D point, @Nonnull Point2D[] polygonVertexes, double epsilon) {
//         for (int vertexIndex = 0, vertexCount = polygonVertexes.length; vertexIndex < vertexCount; ++vertexIndex) {
//             Point2D vertex1 = polygonVertexes[vertexIndex];
//             Point2D vertex2 = polygonVertexes[vertexIndex == vertexCount - 1 ? 0 : vertexIndex + 1];
// 
//             Line2D polygonEdge = Line2D.getLineByTwoPoints(vertex1, vertex2);
// 
//             if (polygonEdge.getSignedDistanceFrom(point) > -epsilon) {
//                 return false;
//             }
//         }
// 
//         return true;
//     }
// 
//     public static boolean isPointInsideConvexPolygon(@Nonnull Point2D point, @Nonnull Point2D[] polygonVertexes) {
//         return isPointInsideConvexPolygon(point, polygonVertexes, 0.0D);
//     }
// 
//     public static boolean isPointOutsideConvexPolygon(
//             @Nonnull Point2D point, @Nonnull Point2D[] polygonVertexes, double epsilon) {
//         for (int vertexIndex = 0, vertexCount = polygonVertexes.length; vertexIndex < vertexCount; ++vertexIndex) {
//             Point2D vertex1 = polygonVertexes[vertexIndex];
//             Point2D vertex2 = polygonVertexes[vertexIndex == vertexCount - 1 ? 0 : vertexIndex + 1];
// 
//             Line2D polygonEdge = Line2D.getLineByTwoPoints(vertex1, vertex2);
// 
//             if (polygonEdge.getSignedDistanceFrom(point) >= epsilon) {
//                 return true;
//             }
//         }
// 
//         return false;
//     }
// 
//     public static boolean isPointOutsideConvexPolygon(@Nonnull Point2D point, @Nonnull Point2D[] polygonVertexes) {
//         return isPointOutsideConvexPolygon(point, polygonVertexes, 0.0D);
//     }
// }


import com.codeforces.commons.geometry.Point2D;
import com.codeforces.commons.text.StringUtil;
import com.codegame.codeseries.notreal2d.util.GeometryUtil;
import javax.annotation.Nonnull;
import static com.codeforces.commons.math.Math.DOUBLE_PI;

package com.codegame.codeseries.notreal2d.form;




/**
 * @author Maxim Shipko (sladethe@gmail.com)
 *         Date: 26.06.2015
 */
public class ArcForm extends ThinForm {
    private final double radius;
    private final double angle;
    private final double sector;

    public ArcForm(double radius, double angle, double sector, boolean endpointCollisionEnabled) {
        super(Shape.ARC, endpointCollisionEnabled);

        if (Double.isNaN(radius) || Double.isInfinite(radius) || radius <= 0.0D) {
            throw new IllegalArgumentException(String.format(
                    "Argument 'radius' should be a positive finite number but got %s.", radius
            ));
        }

        if (Double.isNaN(angle) || Double.isInfinite(angle)) {
            throw new IllegalArgumentException(String.format(
                    "Argument 'angle' should be a finite number but got %s.", angle
            ));
        }

        if (Double.isNaN(sector) || Double.isInfinite(sector) || sector <= 0.0D || sector > DOUBLE_PI) {
            throw new IllegalArgumentException(String.format(
                    "Argument 'sector' should be between 0.0 exclusive and 2 * PI inclusive but got %s.", sector
            ));
        }


// Path: src/main/java/com/codegame/codeseries/notreal2d/util/GeometryUtil.java
// public final class GeometryUtil {
//     private GeometryUtil() {
//         throw new UnsupportedOperationException();
//     }
// 
//     @Contract(pure = true)
//     public static double normalizeAngle(double angle) {
//         while (angle > PI) {
//             angle -= DOUBLE_PI;
//         }
// 
//         while (angle < -PI) {
//             angle += DOUBLE_PI;
//         }
// 
//         return angle;
//     }
// 
//     @Contract(pure = true)
//     public static boolean isAngleBetween(double angle, double startAngle, double finishAngle) {
//         while (finishAngle < startAngle) {
//             finishAngle += DOUBLE_PI;
//         }
// 
//         while (finishAngle - DOUBLE_PI > startAngle) {
//             finishAngle -= DOUBLE_PI;
//         }
// 
//         while (angle < startAngle) {
//             angle += DOUBLE_PI;
//         }
// 
//         while (angle - DOUBLE_PI > startAngle) {
//             angle -= DOUBLE_PI;
//         }
// 
//         return angle >= startAngle && angle <= finishAngle;
//     }
// 
//     public static boolean isPointInsideConvexPolygon(
//             @Nonnull Point2D point, @Nonnull Point2D[] polygonVertexes, double epsilon) {
//         for (int vertexIndex = 0, vertexCount = polygonVertexes.length; vertexIndex < vertexCount; ++vertexIndex) {
//             Point2D vertex1 = polygonVertexes[vertexIndex];
//             Point2D vertex2 = polygonVertexes[vertexIndex == vertexCount - 1 ? 0 : vertexIndex + 1];
// 
//             Line2D polygonEdge = Line2D.getLineByTwoPoints(vertex1, vertex2);
// 
//             if (polygonEdge.getSignedDistanceFrom(point) > -epsilon) {
//                 return false;
//             }
//         }
// 
//         return true;
//     }
// 
//     public static boolean isPointInsideConvexPolygon(@Nonnull Point2D point, @Nonnull Point2D[] polygonVertexes) {
//         return isPointInsideConvexPolygon(point, polygonVertexes, 0.0D);
//     }
// 
//     public static boolean isPointOutsideConvexPolygon(
//             @Nonnull Point2D point, @Nonnull Point2D[] polygonVertexes, double epsilon) {
//         for (int vertexIndex = 0, vertexCount = polygonVertexes.length; vertexIndex < vertexCount; ++vertexIndex) {
//             Point2D vertex1 = polygonVertexes[vertexIndex];
//             Point2D vertex2 = polygonVertexes[vertexIndex == vertexCount - 1 ? 0 : vertexIndex + 1];
// 
//             Line2D polygonEdge = Line2D.getLineByTwoPoints(vertex1, vertex2);
// 
//             if (polygonEdge.getSignedDistanceFrom(point) >= epsilon) {
//                 return true;
//             }
//         }
// 
//         return false;
//     }
// 
//     public static boolean isPointOutsideConvexPolygon(@Nonnull Point2D point, @Nonnull Point2D[] polygonVertexes) {
//         return isPointOutsideConvexPolygon(point, polygonVertexes, 0.0D);
//     }
// }


// Path: src/main/java/com/codegame/codeseries/notreal2d/form/ArcForm.java
import com.codeforces.commons.geometry.Point2D;
import com.codeforces.commons.text.StringUtil;
import com.codegame.codeseries.notreal2d.util.GeometryUtil;
import javax.annotation.Nonnull;
import static com.codeforces.commons.math.Math.DOUBLE_PI;

package com.codegame.codeseries.notreal2d.form;




/**
 * @author Maxim Shipko (sladethe@gmail.com)
 *         Date: 26.06.2015
 */
public class ArcForm extends ThinForm {
    private final double radius;
    private final double angle;
    private final double sector;

    public ArcForm(double radius, double angle, double sector, boolean endpointCollisionEnabled) {
        super(Shape.ARC, endpointCollisionEnabled);

        if (Double.isNaN(radius) || Double.isInfinite(radius) || radius <= 0.0D) {
            throw new IllegalArgumentException(String.format(
                    "Argument 'radius' should be a positive finite number but got %s.", radius
            ));
        }

        if (Double.isNaN(angle) || Double.isInfinite(angle)) {
            throw new IllegalArgumentException(String.format(
                    "Argument 'angle' should be a finite number but got %s.", angle
            ));
        }

        if (Double.isNaN(sector) || Double.isInfinite(sector) || sector <= 0.0D || sector > DOUBLE_PI) {
            throw new IllegalArgumentException(String.format(
                    "Argument 'sector' should be between 0.0 exclusive and 2 * PI inclusive but got %s.", sector
            ));
        }


        this.angle = GeometryUtil.normalizeAngle(angle);
