/// <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); }