protected virtual RealPoint ComputeBarycenter() { double surface = Surface; RealPoint output = null; if (this.Surface == 0) { output = new RealPoint(_sides[0].StartPoint); } else { output = new RealPoint(); foreach (PolygonTriangle t in this.ToTriangles()) { RealPoint barycentreTriangle = t.Barycenter; double otherSurface = t.Surface; if (t.Surface > 0) { output.X += barycentreTriangle.X * otherSurface / surface; output.Y += barycentreTriangle.Y * otherSurface / surface; } } } return(output); }
public Segment(RealPoint start, RealPoint end) { _startPoint = new RealPoint(start); _endPoint = new RealPoint(end); SetLine(StartPoint, EndPoint); }
/// <summary> /// Retourne une ligne qui est tournée de l'angle donné /// </summary> /// <param name="angle">Angle de rotation</param> /// <param name="rotationCenter">Centre de rotation, si null (0, 0) est utilisé</param> /// <returns>Droite tournée de l'angle donné</returns> public Line Rotation(AngleDelta angle, RealPoint rotationCenter = null) { RealPoint p1, p2; if (rotationCenter == null) { rotationCenter = Barycenter; } if (_c == 1) { p1 = new RealPoint(0, _a * 0 + _b); p2 = new RealPoint(1, _a * 1 + _b); p1 = p1.Rotation(angle, rotationCenter); p2 = p2.Rotation(angle, rotationCenter); } else { p1 = new RealPoint(_b, 0); p2 = new RealPoint(_b, 1); } return(new Line(p1, p2)); }
/// <summary> /// Retourne le plus petit cercle contenant tous les points et dont le centre est le barycentre des points /// </summary> /// <param name="pts">Liste des points à contenir</param> /// <returns>Cercle obtenu</returns> public static Circle GetContainingCircle(this IEnumerable <RealPoint> pts) { RealPoint center = pts.GetBarycenter(); double ray = pts.Max(p => p.Distance(center)); return(new Circle(center, ray)); }
/// <summary> /// Retourne un segment qui prolonge l'actuel en ajoutant un point. /// Le résultat est valide uniquement si le point ajouté se trouve sur la droite formée par le segment. /// </summary> /// <param name="pt">Point à ajouter au segment</param> /// <returns>Segment prolongé jusqu'au point donné</returns> public Segment Join(RealPoint pt) { Segment s1 = new Segment(_startPoint, pt); Segment s2 = new Segment(_endPoint, pt); Segment res; if (this.Contains(pt)) { res = new Segment(this); } else if (s1.Contains(_endPoint)) { res = s1; } else if (s2.Contains(_startPoint)) { res = s2; } else { res = null; } return(res); }
protected override RealPoint ComputeBarycenter() { RealPoint output = null; if (Points[0] == Points[1] && Points[0] == Points[2]) { output = new RealPoint(Points[0]); } else if (Points[0] == Points[1]) { output = new Segment(Points[0], Points[2]).Barycenter; } else if (Points[0] == Points[2]) { output = new Segment(Points[1], Points[2]).Barycenter; } else if (Points[1] == Points[2]) { output = new Segment(Points[0], Points[1]).Barycenter; } else { Line d1 = new Line(new Segment(Points[0], Points[1]).Barycenter, Points[2]); Line d2 = new Line(new Segment(Points[1], Points[2]).Barycenter, Points[0]); output = d1.GetCrossingPoints(d2)[0]; } return(output); }
/// <summary> /// Retourne un segment qui est tournée de l'angle donné /// </summary> /// <param name="angle">Angle de rotation</param> /// <param name="rotationCenter">Centre de rotation, si null (0, 0) est utilisé</param> /// <returns>Segment tourné de l'angle donné</returns> public new Segment Rotation(AngleDelta angle, RealPoint rotationCenter = null) { if (rotationCenter == null) { rotationCenter = Barycenter; } return(new Segment(_startPoint.Rotation(angle, rotationCenter), _endPoint.Rotation(angle, rotationCenter))); }
/// <summary> /// Retourne un cercle qui est tourné de l'angle donné /// </summary> /// <param name="angle">Angle de rotation</param> /// <param name="rotationCenter">Centre de rotation, si null le barycentre est utilisé</param> /// <returns>Cercle tourné de l'angle donné</returns> public Circle Rotation(AngleDelta angle, RealPoint rotationCenter = null) { if (rotationCenter == null) { rotationCenter = Barycenter; } return(new Circle(_center.Rotation(angle, rotationCenter), _radius)); }
/// <summary> /// Construit un cercle depuis son centre et son rayon /// </summary> /// <param name="center">Point central du cercle</param> /// <param name="radius">Rayon du cercle</param> public Circle(RealPoint center, double radius) { if (radius < 0) { throw new ArgumentException("Radius must be >= 0"); } _center = center; _radius = radius; }
public Segment(Segment segment) { _startPoint = new RealPoint(segment.StartPoint); _endPoint = new RealPoint(segment.EndPoint); _a = segment.A; _b = segment.B; _c = segment.C; SetLine(StartPoint, EndPoint); }
/// <summary> /// Calcule l'équation de la droite passant par deux points /// </summary> /// <param name="p1">Premier point</param> /// <param name="p2">Deuxième point</param> protected void SetLine(RealPoint p1, RealPoint p2) { if (p2.X - p1.X == 0) { _a = 1; _b = -p1.X; _c = 0; } else { _a = (p2.Y - p1.Y) / (p2.X - p1.X); _b = -(_a * p1.X - p1.Y); _c = 1; } }
/// <summary> /// Retourne un polygone qui est tourné de l'angle donné /// </summary> /// <param name="angle">Angle de rotation</param> /// <param name="rotationCenter">Centre de rotation, si null le barycentre est utilisé</param> /// <returns>Polygone tourné de l'angle donné</returns> public Polygon Rotation(AngleDelta angle, RealPoint rotationCenter = null) { if (rotationCenter == null) { rotationCenter = Barycenter; } Polygon output = new Polygon(Points.ConvertAll(p => p.Rotation(angle, rotationCenter)), false); if (_barycenter.Computed && _barycenter.Value == rotationCenter) { output._barycenter.Value = new RealPoint(_barycenter.Value); } return(output); }
public static List <RealPoint> CircleAndCircle(Circle circle1, Circle circle2) { List <RealPoint> output = new List <RealPoint>(); bool aligned = Math.Abs(circle2.Center.Y - circle1.Center.Y) < RealPoint.PRECISION; if (aligned)// Cercles non alignés horizontalement (on pivote pour les calculs, sinon division par 0) { circle2 = circle2.Rotation(90, circle1.Center); } RealPoint oc1 = new RealPoint(circle2.Center), oc2 = new RealPoint(circle1.Center); double b = circle2.Radius, c = circle1.Radius; double a = (-(Math.Pow(oc1.X, 2)) - (Math.Pow(oc1.Y, 2)) + Math.Pow(oc2.X, 2) + Math.Pow(oc2.Y, 2) + Math.Pow(b, 2) - Math.Pow(c, 2)) / (2 * (oc2.Y - oc1.Y)); double d = ((oc2.X - oc1.X) / (oc2.Y - oc1.Y)); double A = Math.Pow(d, 2) + 1; double B = -2 * oc1.X + 2 * oc1.Y * d - 2 * a * d; double C = Math.Pow(oc1.X, 2) + Math.Pow(oc1.Y, 2) - 2 * oc1.Y * a + Math.Pow(a, 2) - Math.Pow(b, 2); double delta = Math.Pow(B, 2) - 4 * A * C; if (delta >= 0) { double x1 = (-B + Math.Sqrt(delta)) / (2 * A); double y1 = a - x1 * d; output.Add(new RealPoint(x1, y1)); if (delta > 0) { double x2 = (-B - Math.Sqrt(delta)) / (2 * A); double y2 = a - x2 * d; output.Add(new RealPoint(x2, y2)); } } if (aligned) { output = output.ConvertAll(p => p.Rotation(-90, circle1.Center)); } return(output); }
/// <summary> /// Construit un rectangle à partir du point en haut à gauche, de la largeur et de la hauteur /// </summary> /// <param name="topLeft">Point en haut à gauche du rectangle</param> /// <param name="width">Largeur du rectangle</param> /// <param name="heigth">Hauteur du rectangle</param> public PolygonRectangle(RealPoint topLeft, double width, double heigth) : base() { List <Segment> rectSides = new List <Segment>(); if (topLeft == null) { throw new ArgumentOutOfRangeException(); } topLeft = new RealPoint(topLeft); if (width < 0) { topLeft.X += width; width = -width; } if (heigth < 0) { topLeft.Y += heigth; heigth = -heigth; } List <RealPoint> points = new List <RealPoint> { new RealPoint(topLeft.X, topLeft.Y), new RealPoint(topLeft.X + width, topLeft.Y), new RealPoint(topLeft.X + width, topLeft.Y + heigth), new RealPoint(topLeft.X, topLeft.Y + heigth) }; for (int i = 1; i < points.Count; i++) { rectSides.Add(new Segment(points[i - 1], points[i])); } rectSides.Add(new Segment(points[points.Count - 1], points[0])); BuildPolygon(rectSides, false); }
/// <summary> /// Retourne l'équation de la droite perpendiculaire à celle-ci et passant par un point donné /// </summary> /// <param name="point">Point contenu par la perpendiculaire recherchée</param> /// <returns>Equation de la droite perpendiculaire à celle-ci et passant par le point donné</returns> public Line GetPerpendicular(RealPoint point) { // Si je suis une droite verticale, je retourne l'horizontale qui passe par le point if (C == 0) { return(new Line(0, point.Y)); } // Si je suis une droite horizontale, je retourne la verticale qui passe par le point else if (A == 0) { return(new Line(1, -point.X, 0)); } // Si je suis une droite banale, je calcule else { double newA = -1 / _a; double newB = -newA * point.X + point.Y; return(new Line(newA, newB)); } }
/// <summary> /// Retourne le cercle correspondant le mieux aux points données. /// </summary> /// <param name="pts">Points dont on cherche un cercle approchant.</param> /// <returns>Cercle calculé</returns> public static Circle FitCircle(this List <RealPoint> pts) { double[,] m1 = new double[pts.Count, 3]; double[] m2 = new double[pts.Count]; for (int n = 0; n < pts.Count; n++) { m1[n, 0] = -2f * pts[n].X; m1[n, 1] = -2f * pts[n].Y; m1[n, 2] = 1; m2[n] = -(Math.Pow(pts[n].X, 2) + Math.Pow(pts[n].Y, 2)); } double[,] m3 = Matrix.Transpose(m1); double[,] m4 = Matrix.Inverse3x3(Matrix.Multiply(m3, m1)); double[] m5 = Matrix.Multiply(m3, m2); double[] m6 = Matrix.Multiply(m4, m5); RealPoint center = new RealPoint(m6[0], m6[1]); double radius = Math.Sqrt(Math.Pow(center.X, 2) + Math.Pow(center.Y, 2) - m6[2]); return(new Circle(center, radius)); }
/// <summary> /// Retourne la projection hortogonale du point sur la droite. /// </summary> /// <param name="point">Point à projet sur la droite</param> /// <returns>Projection du point sur la droite</returns> public RealPoint GetProjection(RealPoint point) { return(GetCrossingPoints(GetPerpendicular(point))[0]);; }
/// <summary> /// Construit un triangle à partir de ses 3 sommets /// </summary> /// <param name="p1">Sommet 1</param> /// <param name="p2">Sommet 2</param> /// <param name="p3">Sommet 3</param> public PolygonTriangle(RealPoint p1, RealPoint p2, RealPoint p3) : base(new List <RealPoint>() { p1, p2, p3 }) { // L'interet du triangle c'est qu'il est simple de calculer son aire et son barycentre et qu'on s'en sert pour calculer ceux de polygones quelconques }
/// <summary> /// Construit un cercle depuis un autre cercle /// </summary> /// <param name="circle">cercle à copier</param> public Circle(Circle circle) { _center = circle._center; _radius = circle._radius; }
/// <summary> /// Construit la droite passant par deux points /// </summary> /// <param name="p1">Premier point</param> /// <param name="p2">Deuxième point</param> public Line(RealPoint p1, RealPoint p2) { SetLine(p1, p2); }
/// <summary> /// Retourne une copie de la forme ayant subit une rotation /// </summary> /// <param name="shape">Forme à tourner</param> /// <param name="angle">Angle de rotation</param> /// <param name="rotationCenter">Centre de rotation. Si null alors le barycentre est utilisé.</param> /// <returns>Nouvelle forme ayant subit la rotation</returns> public static IShape Rotation(this IShape shape, AngleDelta angle, RealPoint rotationCenter = null) { return(((IShapeModifiable <IShape>)shape).Rotation(angle, rotationCenter)); }