/// <summary> /// Distance between a point and the shape. /// </summary> /// <param name="pt">Test point</param> /// <returns>Distance from point to nearest point on shape</returns> public override float Distance(Vector2 pt) { float distance = Mathf.Infinity; float segDist; int count = closed ? vertices.Length : vertices.Length - 1; for (int i = 0; i < count; i++) { Vertex vert = vertices[i]; Vertex vertNext = vertices[NextIndex(i)]; if (vertices[i].segmentCurves) { segDist = VectorShapeUtils.DistancePointToBezierCurve(pt, vert.position, vert.exitCP, vertNext.enterCP, vertNext.position); } else { segDist = VectorShapeUtils.DistancePointToLineSegment(pt, vert.position, vertNext.position); } if (segDist < distance) { distance = segDist; } } return(distance); }
/// <summary> /// Build a 2D bounding box for the shape. /// </summary> protected override void GenerateBounds() { // TO DO // http://www.iquilezles.org/www/articles/bezierbbox/bezierbbox.htm int bezierSteps = VectorShapeUtils.bezierSteps; List <Vector2> pointList = new List <Vector2>(); float step = 1f / bezierSteps; for (int i = 0; i < vertices.Length; i++) { Vertex vert = vertices[i]; pointList.Add(vert.position); if (vert.segmentCurves) { Vertex vertNext = vertices[NextIndex(i)]; float t = step; for (int j = 1; j < bezierSteps; j++) { pointList.Add(VectorShapeUtils.EvaluateCubicCurve(vert.position, vert.exitCP, vertNext.enterCP, vertNext.position, t)); t += step; } } } shapeBounds = VectorUtils.Bounds(pointList); boundsDirty = false; }
/// <summary> /// Build a 2D bounding box for the shape. /// </summary> protected override void GenerateBounds() { if (_components.Count == 0) { shapeBounds = new Rect(); } else { shapeBounds = _components[0].ShapeBounds; for (int i = 1; i < _components.Count; i++) { shapeBounds = VectorShapeUtils.RectUnion(shapeBounds, _components[i].ShapeBounds); } } boundsDirty = false; }
/// <summary> /// Distance between a point and the shape. /// </summary> /// <param name="pt">Test point</param> /// <param name="mode">Snap modes to consider</param> /// <returns>Distance from point to nearest point on shape</returns> public override SnapPoint GetSnap(Vector2 pt, SnapPoint.Mode mode) { SnapPoint snap = new SnapPoint(); float distance = float.MaxValue; if ((mode & SnapPoint.Mode.Center) != 0) { if (closed && (vertices.Length > 0)) { Vector2 center = new Vector2(); for (int i = 0; i < vertices.Length; i++) { center += vertices[i].position; } center /= vertices.Length; float d = Vector2.Distance(pt, center); if (d < distance) { distance = d; snap.mode = SnapPoint.Mode.Center; snap.point = center; } } } if ((mode & SnapPoint.Mode.Endpoint) != 0) { for (int i = 0; i < vertices.Length; i++) { float d = Vector2.Distance(pt, vertices[i].position); if (d < distance) { distance = d; snap.mode = SnapPoint.Mode.Endpoint; snap.point = vertices[i].position; } } } if ((mode & SnapPoint.Mode.Midpoint) != 0) { int count = closed ? vertices.Length : vertices.Length - 1; for (int i = 0; i < count; i++) { Vertex vert = vertices[i]; Vertex vertNext = vertices[NextIndex(i)]; Vector2 midPoint; if (vertices[i].segmentCurves) { midPoint = VectorShapeUtils.EvaluateCubicCurve(vert.position, vert.exitCP, vertNext.enterCP, vertNext.position, 0.5f); } else { midPoint = (vert.position + vertNext.position) / 2f; } float d = Vector2.Distance(pt, midPoint); if (d < distance) { distance = d; snap.mode = SnapPoint.Mode.Midpoint; snap.point = midPoint; } } } if ((mode & SnapPoint.Mode.Edge) != 0) { int count = closed ? vertices.Length : vertices.Length - 1; for (int i = 0; i < count; i++) { Vertex vert = vertices[i]; Vertex vertNext = vertices[NextIndex(i)]; Vector2 closest; if (vertices[i].segmentCurves) { closest = VectorShapeUtils.ClosetPointOnBezierCurve(pt, vert.position, vert.exitCP, vertNext.enterCP, vertNext.position); } else { closest = VectorShapeUtils.ClosestPointOnLineSegment(pt, vert.position, vertNext.position); } float d = Vector2.Distance(pt, closest); if (d < distance) { distance = d; snap.mode = SnapPoint.Mode.Edge; snap.point = closest; } } } return(snap); }
/// <summary> /// Build a 2D collider for the shape. /// </summary> protected override void AddColliderToGO(GameObject target) { PolygonCollider2D[] polyColliders = target.GetComponents <PolygonCollider2D>(); PolygonCollider2D polyCollider = null; for (int i = 0; i < polyColliders.Length; i++) { if (polyColliders[i].name == this.guid) { polyCollider = polyColliders[i]; } } EdgeCollider2D[] edgeColliders = target.GetComponents <EdgeCollider2D>(); EdgeCollider2D edgeCollider = null; for (int i = 0; i < edgeColliders.Length; i++) { if (edgeColliders[i].name == this.guid) { edgeCollider = edgeColliders[i]; break; } } if (closed) { if (polyCollider == null) { polyCollider = target.AddComponent <PolygonCollider2D>(); polyCollider.name = this.guid; } if (edgeCollider != null) { Object.Destroy(edgeCollider); } } else { if (edgeCollider == null) { edgeCollider = target.AddComponent <EdgeCollider2D>(); edgeCollider.name = this.guid; } if (polyCollider != null) { Object.Destroy(polyCollider); } } int bezierSteps = VectorShapeUtils.bezierSteps; List <Vector2> pointList = new List <Vector2>(); float step = 1f / bezierSteps; int edgeCount = closed ? vertices.Length : vertices.Length - 1; for (int i = 0; i < edgeCount; i++) { Vertex vert = vertices[i]; pointList.Add(vert.position); if (vert.segmentCurves) { Vertex vertNext = vertices[NextIndex(i)]; float t = step; for (int j = 1; j < bezierSteps; j++) { pointList.Add(VectorShapeUtils.EvaluateCubicCurve(vert.position, vert.exitCP, vertNext.enterCP, vertNext.position, t)); t += step; } } } if (closed) { polyCollider.points = pointList.ToArray(); } else { edgeCollider.points = pointList.ToArray(); } }