123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace bbiwarg.Utility
- {
- public enum LineSide {
- onLine = 0,
- above = 1,
- below = 2
- }
- class Line2D
- {
- private Vector2D p1;
- private Vector2D p2;
- private Vector2D direction;
- private float length;
- private int numCombinedLines;
- public Vector2D P1 { get { return p1; } private set { p1 = value; } }
- public Vector2D P2 { get { return p2; } private set { p2 = value; } }
- public Vector2D Direction { get { return direction; } private set { direction = value; } }
- public float Length { get { return length; } private set { length = value; } }
- public int NumCombinedLines { get { return numCombinedLines; } private set { numCombinedLines = value; } }
- public Line2D(Vector2D p1, Vector2D p2) {
- setPoints(p1, p2);
- NumCombinedLines = 1;
- }
- public Line2D(List<Line2D> lines) {
- //list all points
- List<Vector2D> points = new List<Vector2D>();
- List<Vector2D> directions = new List<Vector2D>();
- NumCombinedLines = 0;
- foreach (Line2D line in lines) {
- points.Add(line.P1);
- points.Add(line.P2);
- directions.Add(line.Direction);
- NumCombinedLines += line.NumCombinedLines;
- }
- //find two points with max-distance
- Vector2D a = points[0];
- Vector2D b = points[0];
- float length = 0;
- foreach (Vector2D p in points) {
- float distanceToA = p.getDistanceTo(a);
- float distanceToB = p.getDistanceTo(b);
- if (distanceToA > length && distanceToA >= distanceToB) {
- b = p;
- length = distanceToA;
- }
- else if (distanceToB > length && distanceToB > distanceToA) {
- a = p;
- length = distanceToA;
- }
- }
- //project a and b on mean-line
- Vector2D meanPoint = Vector2D.mean(points);
- Vector2D meanDirection = Vector2D.mean(directions);
- Line2D meanLine = new Line2D(meanPoint, meanPoint + meanDirection);
- Vector2D meanA = meanLine.projectToLine(a);
- Vector2D meanB = meanLine.projectToLine(b);
- setPoints(meanA, meanB);
- }
- private void setPoints(Vector2D p1, Vector2D p2) {
- //endpoints
- P1 = p1;
- P2 = p2;
- //direction
- direction = (P1-P2).normalize();
- //length
- Length = P1.getDistanceTo(P2);
- }
- public float getAngleBetween(Line2D line) {
- float angle = direction.getAngleBetween(line.Direction);
- return Math.Min(angle, 180-angle);
- }
- public float getParallelDistanceTo(Line2D line) {
- if (onSide(line.P1) != onSide(line.P2)) return 0;
- Vector2D a1 = projectToLine(line.P1);
- Vector2D a2 = projectToLine(line.P2);
- float distanceA1 = a1.getDistanceTo(line.P1);
- float distanceA2 = a2.getDistanceTo(line.P2);
- return Math.Min(distanceA1, distanceA2);
- }
- public float getVerticalDistanceTo(Line2D line) {
- Vector2D a1 = projectToLine(line.P1);
- Vector2D a2 = projectToLine(line.P2);
- if (P1.isInBox(a1, a2) || P2.isInBox(a1, a2)) return 0;
- float distanceP1A1 = P1.getDistanceTo(a1);
- float distanceP1A2 = P1.getDistanceTo(a2);
- float distanceP2A1 = p2.getDistanceTo(a1);
- float distanceP2A2 = p2.getDistanceTo(a2);
- return Math.Min(Math.Min(distanceP1A1, distanceP1A2), Math.Min(distanceP2A1, distanceP2A2));
- }
- public LineSide onSide(Vector2D point) {
- float yPerX = direction.Y / direction.X;
- float xDiff = point.X - P1.X;
- float newY = P1.Y + yPerX * xDiff;
- if (newY < point.Y) return LineSide.above;
- else if (newY > point.Y) return LineSide.below;
- else return LineSide.onLine;
- }
- public Vector2D projectToLine(Vector2D point) {
- float px = point.X, py = point.Y, dx = Direction.X, dy = Direction.Y, ox = P1.X, oy = P1.Y;
- float diffx = px - ox;
- float diffy = py - oy;
- float diff_d = (diffx * dx + diffy * dy);
- float d_d = (dx * dx + dy * dy);
- float q = diff_d / d_d;
- float newX = ox + q * dx;
- float newY = oy + q * dy;
- return new Vector2D(newX, newY);
- }
- public override string ToString()
- {
- return (int)P1.X + "|" + (int)P1.Y + " --- " + (int)P2.X + "|" + (int)P2.Y;
- }
- }
- }
|