public static float GetDistanceWithParallelogram(Vector3 anchorPoint, Vector3 baseVertex, Vector3 edge1, Vector3 edge2, out Vector3 location) { // 平行四辺形のある平面の法線 Vector3 normOnParallelogram = Vector3.Normalize(Vector3.Cross(edge1, edge2)); // baseVertexへ Vector3 toBaseVertex = baseVertex - anchorPoint; // anchorPointから平行四辺形のある平面への最短ベクトル(垂線) Vector3 perpendicular = normOnParallelogram * Vector3.Dot(toBaseVertex, normOnParallelogram); // 垂線の足 Vector3 foot = anchorPoint + perpendicular; // 垂線の足が平行四辺形の中かどうか if (GeometryCalc.PointOverParallelogram(foot, baseVertex, edge1, edge2)) { location = foot; return(perpendicular.Length()); } Vector3 oppositeVertex = baseVertex + edge1 + edge2; Vector3 location1, location2, location3, location4; float distance1 = GeometryCalc.GetDistanceWithLine(anchorPoint, baseVertex, baseVertex + edge1, out location1); float distance2 = GeometryCalc.GetDistanceWithLine(anchorPoint, baseVertex, baseVertex + edge2, out location2); float distance3 = GeometryCalc.GetDistanceWithLine(anchorPoint, oppositeVertex, oppositeVertex - edge1, out location3); float distance4 = GeometryCalc.GetDistanceWithLine(anchorPoint, oppositeVertex, oppositeVertex - edge2, out location4); float minDistance = new float[] { distance1, distance2, distance3, distance4 }.Min(); if (minDistance == distance1) { location = location1; } else if (minDistance == distance2) { location = location2; } else if (minDistance == distance3) { location = location3; } else { location = location4; } return(minDistance); }
/// <summary> /// 点と三角形ポリゴンとの最短距離を返します /// </summary> /// <param name="anchorPoint">基準点</param> /// <param name="vertex1">三角形の頂点</param> /// <param name="vertex2">三角形の頂点</param> /// <param name="vertex3">三角形の頂点</param> /// <param name="location">基準点に対して最も近い三角形上の点</param> /// <returns></returns> public static float GetDistanceWithTriangle(Vector3 anchorPoint, Vector3 vertex1, Vector3 vertex2, Vector3 vertex3, out Vector3 location) { Vector3 edge2 = vertex2 - vertex1; Vector3 edge3 = vertex3 - vertex1; Vector3 triangleVert = Vector3.Normalize(Vector3.Cross(edge2, edge3)); Vector3 toAnchor = anchorPoint - vertex1; float vertDistance = Vector3.Dot(triangleVert, toAnchor); Vector3 testDir = -triangleVert * vertDistance * 2; Motion.Old.MotionDataLine vertLine = new Motion.Old.MotionDataLine(anchorPoint, testDir); float distance; if (GeometryCalc.GetCollisionTriangle(vertLine.End, vertLine.AnotherEnd, vertex1, vertex2, vertex3, out distance)) { location = anchorPoint + Vector3.Normalize(testDir) * distance; return(distance); } Vector3 location1, location2, location3; float distance1 = GeometryCalc.GetDistanceWithLine(anchorPoint, vertex1, vertex2, out location1); float distance2 = GeometryCalc.GetDistanceWithLine(anchorPoint, vertex2, vertex3, out location2); float distance3 = GeometryCalc.GetDistanceWithLine(anchorPoint, vertex3, vertex1, out location3); if (distance1 < distance2 && distance1 < distance3) { location = location1; return(distance1); } else if (distance2 < distance1 && distance2 < distance3) { location = location2; return(distance2); } else { location = location3; return(distance3); } }
public static bool GetCollisionParallelogram(Vector3 lineSource, Vector3 lineDestination, Vector3 baseVertex, Vector3 edge1, Vector3 edge2, out float distance) { distance = float.MaxValue; Vector3 lineEdge = lineDestination - lineSource; // 平行四辺形のある平面の法線 Vector3 normOnParallelogram = Vector3.Normalize(Vector3.Cross(edge1, edge2)); // baseVertexへ Vector3 toBaseVertex = baseVertex - lineSource; // 平面の法線成分 float toBaseVertexDistance = Vector3.Dot(normOnParallelogram, toBaseVertex); float lineEdgeDistance = Vector3.Dot(normOnParallelogram, lineEdge); if (lineEdgeDistance == 0) { // 引数の線分と平行四辺形が平行な時 return(false); } float ratio = toBaseVertexDistance / lineEdgeDistance; if (ratio < 0 && 1 < ratio) { // 向きが逆であるか,長さが足りない return(false); } // 引数の線分と平行四辺形のある平面との交点へのベクトル Vector3 lineEdgeToParallelogram = lineEdge * ratio; // 引数の線分と平行四辺形のある平面との交点 Vector3 onPlane = lineSource + lineEdgeToParallelogram; if (GeometryCalc.PointOverParallelogram(onPlane, baseVertex, edge1, edge2)) { distance = lineEdgeToParallelogram.Length(); return(true); } return(false); }