/// <summary>
        /// a1→a2の直線に並行する座標を計算する
        /// size:平行に離す距離
        /// direction:平行にする方向を進行方向の右側か左側かの設定 true:左側、false:右側
        /// </summary>
        /// <param name="a1"></param>
        /// <param name="a2"></param>
        /// <param name="size"></param>
        /// <param name="direction"></param>
        /// <returns></returns>
        public static Coordinate[] calcParallelCoordinate(Coordinate a1, Coordinate a2, float size, bool direction)
        {
            Vector2 vec = CoordinateUtility.getVector2(a1, a2);

            double radian = Math.PI * 90.0 / 180.0;

            if (!direction)
            {
                radian *= -1;
            }
            // radianが正の場合、反時計回りに回転 負の場合、時計回りに回転

            // 回転行列
            float     cos    = (float)Math.Cos(radian);
            float     sin    = (float)Math.Sin(radian);
            Matrix3x2 matrix = new Matrix3x2(cos, -sin, sin, cos, 0, 0);

            // 直行するベクトル
            Vector2 vec_cross = new Vector2(matrix.M11 * vec.X + matrix.M12 * vec.Y, matrix.M21 * vec.X + matrix.M22 * vec.Y);

            Vector2 normalize_vec_cross = Vector2.Normalize(vec_cross);

            Coordinate[] coodinates = new Coordinate[2];

            // 起点側
            coodinates[0] = new Coordinate(a1.x + normalize_vec_cross.X * size, a1.y + normalize_vec_cross.Y * size);

            // 終点側
            coodinates[1] = new Coordinate(a2.x + normalize_vec_cross.X * size, a2.y + normalize_vec_cross.Y * size);

            return(coodinates);
        }
        /// <summary>
        /// a1-a2ベクトル, b1-b2ベクトルが同じ方向か間逆の方向の場合trueを返します
        /// </summary>
        /// <param name="a1"></param>
        /// <param name="a2"></param>
        /// <param name="b1"></param>
        /// <param name="b2"></param>
        /// <returns></returns>
        public static Boolean checkParallel(Coordinate a1, Coordinate a2, Coordinate b1, Coordinate b2)
        {
            Vector2 vec1 = CoordinateUtility.getVector2(a1, a2);
            Vector2 vec2 = CoordinateUtility.getVector2(b1, b2);

            return(checkParallel(vec1, vec2));
        }
        /// <summary>
        /// a1-a2線分とb2-b1の線分の交点を計算する
        /// 但し、平行ではなく交点がa1-a2とb2-b1の直線上に見つからないか、線分上に存在しない場合はnullを返す
        /// </summary>
        /// <param name="a1"></param>
        /// <param name="a2"></param>
        /// <param name="b1"></param>
        /// <param name="b2"></param>
        /// <returns></returns>
        public static Coordinate lineSegmentIntersection(Coordinate a1, Coordinate a2, Coordinate b1, Coordinate b2)
        {
            Coordinate coord = CoordinateUtility.intersection(a1, a2, b1, b2);

            if (CoordinateUtility.checkPointAndLineSegment(a1, a2, coord) && CoordinateUtility.checkPointAndLineSegment(b1, b2, coord))
            {
                return(coord);
            }

            return(null);
        }
        /// <summary>
        /// a1を中心にa2を回転させた座標を計算する。角度は、rotation > 0 時計回り、rotation < 0 反時計回り rotation は度
        /// </summary>
        /// <param name="a1"></param>
        /// <param name="a2"></param>
        /// <param name="rotation"></param>
        /// <returns></returns>
        public static Coordinate calcRotationCoordinate(Coordinate a1, Coordinate a2, double rotation)
        {
            Vector2 vec = CoordinateUtility.getVector2(a1, a2);

            double radian = Math.PI * 90.0 / 180.0;

            // 回転行列
            float     cos    = (float)Math.Cos(radian);
            float     sin    = (float)Math.Sin(radian);
            Matrix3x2 matrix = new Matrix3x2(cos, -sin, sin, cos, 0, 0);

            // 直行するベクトル
            Vector2 vec_rotate = new Vector2(matrix.M11 * vec.X + matrix.M12 * vec.Y, matrix.M21 * vec.X + matrix.M22 * vec.Y);

            return(new Coordinate(a1.x + vec_rotate.X, a1.y + vec_rotate.Y));
        }
        /// <summary>
        /// a1-a2のベクトル(a1起点)とb2-b1のベクトル(b2起点)の交点を計算する
        /// 但し、平行ではなく交点がa1-a2とb2-b1の直線上に見つからないか、線分上に存在しない場合はa2,b1の中点を返す
        /// </summary>
        /// <param name="a1"></param>
        /// <param name="a2"></param>
        /// <param name="b1"></param>
        /// <param name="b2"></param>
        /// <returns></returns>
        public static Coordinate vectorIntersection(Coordinate a1, Coordinate a2, Coordinate b1, Coordinate b2)
        {
            Coordinate coord = CoordinateUtility.intersection(a1, a2, b1, b2);

            if (CoordinateUtility.getDistance(a1, coord) < CoordinateUtility.getDistance(a2, coord) || CoordinateUtility.getDistance(b2, coord) < CoordinateUtility.getDistance(b1, coord))
            {
                // 交点座標がa1またはb2に近いに近い場合
                if (!CoordinateUtility.checkPointAndLineSegment(a1, a2, coord) && !CoordinateUtility.checkPointAndLineSegment(b1, b2, coord))
                {
                    coord.x = (a2.x + b1.x) / 2.0f;
                    coord.y = (a2.y + b1.y) / 2.0f;
                }
            }

            return(coord);
        }
        /// <summary>
        /// a1座標、a2座標を通過する直線とb1座標、b2座標を通過する直線の交点を計算します。
        /// </summary>
        /// <param name="a1"></param>
        /// <param name="a2"></param>
        /// <param name="b1"></param>
        /// <param name="b2"></param>
        /// <returns></returns>
        public static Coordinate intersection(Coordinate a1, Coordinate a2, Coordinate b1, Coordinate b2)
        {
            // 交点座標
            Coordinate cross_coord = new Coordinate();

            if (a1.x == b1.x && a1.y == b1.y)
            {
                // a1とb1が同じ座標の場合
                cross_coord.x = a1.x;
                cross_coord.y = a1.x;

                return(cross_coord);
            }
            else if (a1.x == b2.x && a1.y == b2.y)
            {
                // a1とb2が同じ座標の場合
                cross_coord.x = a1.x;
                cross_coord.y = a1.y;

                return(cross_coord);
            }
            else if (a2.x == b1.x && a2.y == b1.y)
            {
                // a2とb1が同じ座標の場合
                cross_coord.x = a2.x;
                cross_coord.y = a2.y;

                return(cross_coord);
            }
            else if (a2.x == b2.x && a2.y == b2.y)
            {
                // a2とb2が同じ座標の場合
                cross_coord.x = a2.x;
                cross_coord.y = a2.y;

                return(cross_coord);
            }

            // a1-a2, b1-b2の各長さが0でないかチェックする
            var distance_a = CoordinateUtility.getDistance(a1, a2);
            var distance_b = CoordinateUtility.getDistance(b1, b2);

            if (distance_a == 0 || distance_b == 0)
            {
                throw new ArgumentException("distance is 0");
            }

            // aベクトル、bベクトルを作成
            Vector2 vec_a = CoordinateUtility.getVector2(a1, a2);
            Vector2 vec_b = CoordinateUtility.getVector2(b1, b2);

            // a1-a2, b1-b2の向きが同じ方向か間逆の方向かをチェックする
            Boolean parallel = CoordinateUtility.checkParallel(vec_a, vec_b);

            if (parallel)
            {
                throw new ArgumentException("this relationship is parallel");
            }

            // a1-a2, b1-b2の各直線の傾き、切片を計算する
            float[] line_a = CoordinateUtility.getLineVariable(a1, a2);
            float[] line_b = CoordinateUtility.getLineVariable(b1, b2);

            if (float.IsNaN(line_a[0]))
            {
                // a1-a2がY軸に平行な直線の場合
                cross_coord.x = a1.x;
                cross_coord.y = line_b[0] * cross_coord.x + line_b[1]; //  y=ax+b
            }
            else if (float.IsNaN(line_b[0]))
            {
                // b1-b2がY軸に平行な直線の場合
                cross_coord.x = b1.x;
                cross_coord.y = line_a[0] * cross_coord.x + line_a[1]; //  y=ax+b
            }
            else if (line_a[0] == 0.0f)
            {
                // a1-a2がX軸に平行な直線の場合
                cross_coord.x = (line_a[1] - line_b[1]) / line_b[0]; //  x=(y-b)/a
                cross_coord.y = line_a[1];
            }
            else if (line_b[0] == 0.0f)
            {
                // b1-b2がX軸に平行な直線の場合
                cross_coord.x = (line_b[1] - line_a[1]) / line_a[0]; //  x=(y-b)/a
                cross_coord.y = line_b[1];
            }
            else
            {
                // 逆行列から交点を求める
                // m11, m12
                // m21, m22
                // m31=0, m32=0
                // の構造

                // y = p1*x + q1
                // y = p2*x + q2
                // を以下のように展開(行列)
                // |p1 -1||x| = |-p1|
                // |p2 -1||y| = |-p2|
                // x,yは逆行列を求めて右辺との行列の積で計算できる

                Matrix3x2 matrix = new Matrix3x2(line_a[0], -1.0f, line_b[0], -1.0f, 0.0f, 0.0f);
                // 逆行列
                Matrix3x2 matrix_invert;
                Matrix3x2.Invert(matrix, out matrix_invert);

                cross_coord.x = matrix_invert.M11 * -line_a[1] + matrix_invert.M12 * -line_b[1];
                cross_coord.y = matrix_invert.M21 * -line_a[1] + matrix_invert.M22 * -line_b[1];
            }

            return(cross_coord);
        }