/// <summary> /// 与线段的关系 /// </summary> /// <param name="line"></param> /// <returns></returns> public LineRelation CheckLineRelation(LineSegment2D line) { // 快速排斥实验,后续优化实现 // 进行跨立实验 double r1 = Double2.Cross(this.normalizedDir, line.startPoint - this.startPoint); double r2 = Double2.Cross(this.normalizedDir, line.endPoint - this.startPoint); double cross1 = r1 * r2; double t1 = Double2.Cross(line.normalizedDir, this.startPoint - line.startPoint); double t2 = Double2.Cross(line.normalizedDir, this.endPoint - line.startPoint); double cross2 = t1 * t2; if (cross1 > 0 || cross2 > 0) { return(LineRelation.Detach); } else if (cross1 == 0 || cross2 == 0) { if (cross1 == 0) { if (r1 == 0) { if (Double2.Dot(line.startPoint - this.startPoint, line.startPoint - this.endPoint) <= 0) { return(LineRelation.Intersect); } } if (r2 == 0) { if (Double2.Dot(line.endPoint - this.startPoint, line.endPoint - this.endPoint) <= 0) { return(LineRelation.Intersect); } } } if (cross2 == 0) { if (t1 == 0) { if (Double2.Dot(this.startPoint - line.startPoint, this.startPoint - line.endPoint) <= 0) { return(LineRelation.Intersect); } } if (t2 == 0) { if (Double2.Dot(this.endPoint - line.startPoint, this.endPoint - line.endPoint) <= 0) { return(LineRelation.Intersect); } } } return(LineRelation.Detach); } return(LineRelation.Intersect); }
/// <summary> /// 修正near far 点 /// </summary> /// <param name="line"></param> /// <param name="nearPoint"></param> /// <param name="farPoint"></param> protected void ReviseNearFar(LineSegment2D line) { if (Double2.Dot(nearPoint - line.startPoint, line.normalizedDir) <= 0) { nearPoint = line.startPoint; } if (Double2.Dot(line.endPoint - farPoint, line.normalizedDir) <= 0) { farPoint = line.endPoint; } }
/// <summary> /// 获取挡格附近出生点 /// </summary> /// <param name="line"></param> /// <param name="offset"></param> /// <param name="bornPoint"></param> /// <returns></returns> public override bool GetBornPoint(LineSegment2D line, double offset, ref Double2 bornPoint) { Double2 pos1 = Double2.zero; for (int i = 0; i < GetEdgeNum(); i++) { if (line.GetIntersectPoint(GetEdge(i), ref bornPoint, ref pos1) == true) { bornPoint = line.normalizedDir * ((bornPoint - line.startPoint).magnitude + offset) + line.startPoint; return(true); } } return(false); }
/// <summary> /// 与线段的关系 /// </summary> /// <param name="line"></param> /// <returns></returns> public override LineRelation CheckLineRelation(LineSegment2D line) { Double2 pos = Double2.zero; Double2 pos1 = Double2.zero; for (int i = 0; i < GetEdgeNum(); i++) { if (line.GetIntersectPoint(GetEdge(i), ref pos, ref pos1) == true) { return(LineRelation.Intersect); } } return(LineRelation.Detach); }
/// <summary> /// 计算其他辅助数据 /// </summary> /// <param name="line"></param> public void CalcHelpData(LineSegment2D line, double offset, Double2 near, Double2 far) { isCross = true; if (this.listpath != null && this.listpath.Count > 0) { this.nearPoint = near; this.nearPoint -= offset * line.normalizedDir; this.farPoint = far; this.farPoint += offset * line.normalizedDir; this.ReviseNearFar(line); // 计算时针方向 this.isCounterclockwiseDir = CaclCounterclockwiseDir(line, this.listpath); this.distance = (line.startPoint - nearPoint).sqrMagnitude; } }
/// <summary> /// 获取交点 /// </summary> /// <param name="line"></param> /// <param name="intersectStart"></param> /// <param name="intersectEnd"></param> /// <returns></returns> public override bool GetIntersectPoint(LineSegment2D line, ref Double2 intersectStart, ref Double2 intersectEnd) { List <Double2> listPt = new List <Double2>(); Double2 pos = Double2.zero; Double2 pos1 = Double2.zero; for (int i = 0; i < GetEdgeNum(); i++) { if (GetEdge(i).GetIntersectPoint(line, ref pos, ref pos1) == true) { if (pos == pos1) { if (listPt.Contains(pos) == false) { listPt.Add(pos); } } else { if (listPt.Contains(pos) == false) { listPt.Add(pos); } if (listPt.Contains(pos1) == false) { listPt.Add(pos1); } } } } // 排序从近到远 listPt.Sort((a, b) => MathUtil.GetCompareDis(a, line.startPoint).CompareTo(MathUtil.GetCompareDis(b, line.startPoint))); // if (listPt.Count > 0) { intersectStart = listPt[0]; intersectEnd = listPt[listPt.Count - 1]; return(true); } return(false); }
/// <summary> /// 与多边形的关系 /// </summary> /// <param name="ab"></param> /// <returns>true 相交: false 不相交</returns> public override bool CheckIntersect(Polygon2D ab) { if (ab == null) { return(false); } if (ab.CheckIn(this.circleCenter) == true) { return(true); } for (int i = 0; i < ab.GetEdgeNum(); i++) { LineSegment2D ls = ab.GetEdge(i); if (this.CheckLineRelation(ls) != LineRelation.Detach) { return(true); } } return(false); }
/// <summary> /// 计算超出线段范围 /// </summary> /// <param name="lineStart"></param> /// <param name="lineEnd"></param> /// <param name="listMidPoint"></param> /// <param name="nearestIndex"></param> /// <param name="farestIndex"></param> private static void CalcNearFarest(Double2 lineStart, Double2 lineEnd, List <Double2> listMidPoint, ref int nearestIndex, ref int farestIndex) { if (listMidPoint == null || listMidPoint.Count == 0) { return; } nearestIndex = -1; farestIndex = -1; double outStartdis = 0; double outEnddis = 0; LineSegment2D line = new LineSegment2D(lineStart, lineEnd); for (int i = 0; i < listMidPoint.Count; i++) { ProjectPointInLine pp = line.CheckProjectInLine(listMidPoint[i]); if (pp == ProjectPointInLine.In) { continue; } Double2 projectPoint = line.ProjectPoint(listMidPoint[i]); if (pp == ProjectPointInLine.OutStart) { double dis = (projectPoint - lineStart).sqrMagnitude; if (dis > outStartdis) { outStartdis = dis; nearestIndex = i; } } else if (pp == ProjectPointInLine.OutStart) { double dis = (projectPoint - lineEnd).sqrMagnitude; if (dis > outEnddis) { outEnddis = dis; farestIndex = i; } } } }
public override bool Equals(System.Object obj) { if (obj == null) { return(false); } LineSegment2D p = (LineSegment2D)obj; if ((System.Object)p == null) { return(false); } if ((startPoint == p.startPoint && endPoint == p.endPoint) || (startPoint == p.endPoint && endPoint == p.startPoint)) { return(true); } else { return(false); } }
/// <summary> /// 与线段的关系 /// </summary> /// <param name="line"></param> /// <returns></returns> public override LineRelation CheckLineRelation(LineSegment2D line) { double dis = line.CalcDistance(this.circleCenter); if (dis > this.radius) { return(LineRelation.Detach); } else { double sqrRadius = this.radius * this.radius; if ((this.circleCenter - line.startPoint).sqrMagnitude > sqrRadius) { return(LineRelation.Intersect); } if ((this.circleCenter - line.endPoint).sqrMagnitude > sqrRadius) { return(LineRelation.Intersect); } return(LineRelation.Coincide); } }
/// <summary> /// 计算时钟方向 /// </summary> /// <param name="line"></param> /// <param name="paths"></param> /// <returns></returns> protected bool CaclCounterclockwiseDir(LineSegment2D line, List <Double2> paths) { if (paths == null || paths.Count == 0) { return(true); } Double2 f = Double2.zero; for (int i = 0; i < paths.Count; i++) { f += paths[i]; } f /= paths.Count; double sinAngle = Double2.SinAngle(line.normalizedDir, f - line.startPoint); if (sinAngle < 0) { return(false); } else { return(true); } }
/// <summary> /// 与线段的关系 /// </summary> /// <param name="line"></param> /// <returns></returns> public virtual LineRelation CheckLineRelation(LineSegment2D line) { return(LineRelation.Intersect); }
/// <summary> /// 获取挡格附近出生点 /// </summary> /// <param name="line"></param> /// <param name="offset"></param> /// <param name="bornPoint"></param> /// <returns></returns> public virtual bool GetBornPoint(LineSegment2D line, float offset, ref Float2 bornPoint) { return(false); }
/// <summary> /// 获取交点 /// </summary> /// <param name="line"></param> /// <param name="intersectPoint"></param> /// <returns></returns> public bool GetIntersectPoint(LineSegment2D line, ref Double2 intersectStartPoint, ref Double2 intersectEndPoint) { if (CheckLineRelation(line) == LineRelation.Intersect) { Double2 aixsVector = AixsVector(line.startPoint); double distance = aixsVector.magnitude; if (distance == 0) { if (Double2.Cross(line.normalizedDir, this.normalizedDir) == 0) { if (Double2.Dot(line.normalizedDir, this.normalizedDir) > 0) { if (Double2.Dot(line.normalizedDir, this.startPoint - line.startPoint) > 0) { intersectStartPoint = this.startPoint; } else { intersectStartPoint = line.startPoint; } // if (Double2.Dot(line.normalizedDir, this.endPoint - line.endPoint) > 0) { intersectEndPoint = line.endPoint; } else { intersectEndPoint = this.endPoint; } } else { if (Double2.Dot(line.normalizedDir, this.startPoint - line.endPoint) > 0) { intersectEndPoint = line.endPoint; } else { intersectEndPoint = line.startPoint; } // if (Double2.Dot(line.normalizedDir, this.endPoint - line.startPoint) > 0) { intersectStartPoint = this.endPoint; } else { intersectStartPoint = line.startPoint; } } } else { intersectStartPoint = line.startPoint; intersectEndPoint = line.startPoint; } return(true); } else { if (CalcDistance(line.endPoint) == 0) { intersectStartPoint = line.endPoint; intersectEndPoint = intersectStartPoint; return(true); } // double dot = Double2.Dot(aixsVector.normalized, line.normalizedDir); if (dot == 0) { return(false); } else { intersectStartPoint = line.startPoint - distance / dot * line.normalizedDir; intersectEndPoint = intersectStartPoint; return(true); } } } return(false); }
/// <summary> /// 获取交点 /// </summary> /// <param name="line"></param> /// <param name="intersectStart"></param> /// <param name="intersectEnd"></param> /// <returns></returns> public virtual bool GetIntersectPoint(LineSegment2D line, ref Float2 intersectStart, ref Float2 intersectEnd) { return(false); }
/// <summary> /// 获取交点 /// </summary> /// <param name="line"></param> /// <param name="intersectPoint"></param> /// <returns></returns> public bool GetIntersectPoint(LineSegment2D line, ref Double2 intersectStartPoint, ref Double2 intersectEndPoint) { return(line.GetIntersectPoint(this, ref intersectStartPoint)); }
/// <summary> /// 与线段的关系 /// </summary> /// <param name="line"></param> /// <returns></returns> public LineRelation CheckLineRelation(LineSegment2D line) { return(line.CheckLineRelation(this)); }
/// <summary> /// 最短射线包围盒路径 /// </summary> /// <param name="line">线段</param> /// <param name="offset">偏移值</param> /// <param name="rbi">包围盒信息</param> /// <returns>true,表示线段与aabb有相交,并返回最短包围路径</returns> public override RBIResultType RayboundingNearestPath(LineSegment2D line, double offset, ref RayboundingInfo rbi) { if (rbi == null) { rbi = new RayboundingInfo(); } int index = 0; Double3[] lineArray = new Double3[2]; Double2 intersectionPoint = Double2.zero; Double2 pos1 = Double2.zero; if (line.GetIntersectPoint(GetEdge(0), ref intersectionPoint, ref pos1) == true) { lineArray[index] = new Double3(intersectionPoint.x, intersectionPoint.y, 1); index++; } if (line.GetIntersectPoint(GetEdge(2), ref intersectionPoint, ref pos1) == true) { lineArray[index] = new Double3(intersectionPoint.x, intersectionPoint.y, 3); index++; } if (index < 2) { if (line.GetIntersectPoint(GetEdge(3), ref intersectionPoint, ref pos1) == true) { lineArray[index] = new Double3(intersectionPoint.x, intersectionPoint.y, 4); index++; } } if (index < 2) { if (line.GetIntersectPoint(GetEdge(1), ref intersectionPoint, ref pos1) == true) { lineArray[index] = new Double3(intersectionPoint.x, intersectionPoint.y, 2); index++; } } if (index == 2) { double v1 = (new Double2(lineArray[0].x, lineArray[0].y) - line.startPoint).sqrMagnitude; double v2 = (new Double2(lineArray[1].x, lineArray[1].y) - line.startPoint).sqrMagnitude; Double2 s; Double2 e; if (v1 < v2) { s = new Double2(lineArray[0].x, lineArray[0].y); e = new Double2(lineArray[1].x, lineArray[1].y); RayboundingNearestPath(new Double3(s.x, s.y, lineArray[0].z), new Double3(e.x, e.y, lineArray[1].z), offset, ref rbi.listpath); } else { e = new Double2(lineArray[0].x, lineArray[0].y); s = new Double2(lineArray[1].x, lineArray[1].y); RayboundingNearestPath(new Double3(s.x, s.y, lineArray[1].z), new Double3(e.x, e.y, lineArray[0].z), offset, ref rbi.listpath); } if (rbi.listpath != null && rbi.listpath.Count > 0) { rbi.CalcHelpData(line, offset, s, e); return(RBIResultType.Succ); } return(RBIResultType.Fail); } else { return(RBIResultType.Fail); } }
/// <summary> /// 最短射线包围盒路径 /// </summary> /// <param name="line">线段</param> /// <param name="offset">偏移值</param> /// <param name="rbi">包围盒信息</param> /// <returns>true,表示线段与aabb有相交,并返回最短包围路径</returns> public override RBIResultType RayboundingNearestPath(LineSegment2D line, double offset, ref RayboundingInfo rbi) { if (rbi == null) { rbi = new RayboundingInfo(); } Double2 diff = this.circleCenter - line.startPoint; if (diff == Double2.zero) { return(RBIResultType.Fail); } // Double2 projectoint = line.ProjectPoint(this.circleCenter); diff = this.circleCenter - projectoint; // 跟直线相交奥 double dis = diff.sqrMagnitude - this.radius * this.radius; if (dis >= 0) { return(RBIResultType.Fail); } dis = -dis; // 在同侧不行。 Double2 diff1 = line.startPoint - projectoint; Double2 diff2 = line.endPoint - projectoint; if (Double2.Dot(diff1, diff2) >= 0) { return(RBIResultType.Fail); } // if (diff1.sqrMagnitude < dis || diff2.sqrMagnitude < dis) { return(RBIResultType.Fail); } dis = System.Math.Sqrt(dis) + offset; Double2 p1 = projectoint - line.normalizedDir * dis; Double2 p2 = projectoint + line.normalizedDir * dis; double bigRadius = this.radius + offset; double angle = SignedAngleInCircle(p1 - this.circleCenter, p2 - this.circleCenter, bigRadius); int count = (int)(System.Math.Abs(angle / 0.25f)); double diffangle = angle / count; List <Double2> listpath = new List <Double2>(); Double2 startVector = (p1 - this.circleCenter).normalized * bigRadius; for (int i = 1; i <= count - 1; i++) { Double2 rorateVector = Double2.Rotate(startVector, -diffangle * i); listpath.Add(rorateVector + this.circleCenter); } rbi.listpath = listpath; if (rbi.listpath != null && rbi.listpath.Count > 0) { rbi.CalcHelpData(line, offset, p1, p2); return(RBIResultType.Succ); } return(RBIResultType.Fail); }
/// <summary> /// 最短射线包围盒路径 /// </summary> /// <param name="line">线段</param> /// <param name="offset">偏移值</param> /// <param name="paths">返回路径</param> /// <returns>true,表示线段与aabb有相交,并返回最短包围路径</returns> public virtual bool RayboundingNearestPath(LineSegment2D line, float offset, ref List <Float2> paths) { return(false); }
/// <summary> /// 最短射线包围盒路径 /// </summary> /// <param name="line">线段</param> /// <param name="offset">偏移值</param> /// <param name="rbi">包围盒信息</param> /// <returns>true,表示线段与aabb有相交,并返回最短包围路径</returns> public override RBIResultType RayboundingNearestPath(LineSegment2D line, double offset, ref RayboundingInfo rbi) { if (rbi == null) { rbi = new RayboundingInfo(); } List <Double3> lineArray = new List <Double3>(); Double2 intersectionPoint = Double2.zero; Double2 pos1 = Double2.zero; for (int i = 0; i < this.pointArr.Length; i++) { if (line.GetIntersectPoint(GetEdge(i), ref intersectionPoint, ref pos1) == true) { lineArray.Add(new Double3(intersectionPoint.x, intersectionPoint.y, i)); } } int count = lineArray.Count; if (count == 0) { return(RBIResultType.Fail); } else if (count % 2 == 1) { lineArray.Sort((x, y) => MathUtil.GetCompareDis(new Double2(x.x, x.y), line.startPoint).CompareTo(MathUtil.GetCompareDis(new Double2(y.x, y.y), line.startPoint))); if (CheckIn(line.startPoint) == true) { rbi.SetNear(line, offset, new Double2(lineArray[0].x, lineArray[0].y)); return(RBIResultType.UnCrossstartPointIn); } else { rbi.SetNear(line, offset, new Double2(lineArray[count - 1].x, lineArray[count - 1].y)); return(RBIResultType.UnCrossendPointIn); } } else { // 先按距离进行排序。 lineArray.Sort((x, y) => MathUtil.GetCompareDis(new Double2(x.x, x.y), line.startPoint).CompareTo(MathUtil.GetCompareDis(new Double2(y.x, y.y), line.startPoint))); // bool isCross = true; bool isPathDir = CheckPathDir(lineArray[0], lineArray[lineArray.Count - 1], ref isCross); if (isCross == false) { rbi.SetNear(line, offset, new Double2(lineArray[0].x, lineArray[0].y)); return(RBIResultType.UnCross); } List <Double2> temppaths = new List <Double2>(); RayboundingNearestPath(lineArray[0], lineArray[lineArray.Count - 1], offset, isPathDir, ref temppaths); if (rbi.listpath == null) { rbi.listpath = temppaths; } else { rbi.listpath.AddRange(temppaths); } // 排斥需要扣除的点。 for (int i = 1; i < lineArray.Count - 1; i += 2) { if (CheckisSubChild((int)lineArray[0].z, (int)lineArray[lineArray.Count - 1].z, isPathDir, (int)lineArray[i].z, (int)lineArray[i + 1].z) == false) { continue; } List <Double2> listTemp = new List <Double2>(); RayboundingNearestPath(lineArray[i], lineArray[i + 1], offset, isPathDir, ref listTemp); if (listTemp.Count > 0) { foreach (Double2 pos in listTemp) { rbi.listpath.Remove(pos); } } } // if (rbi.listpath != null && rbi.listpath.Count > 0) { rbi.CalcHelpData(line, offset, new Double2(lineArray[0].x, lineArray[0].y), new Double2(lineArray[lineArray.Count - 1].x, lineArray[lineArray.Count - 1].y)); return(RBIResultType.Succ); } return(RBIResultType.Fail); } }