VectSharp  2.2.1
A light library for C# vector graphics
Point.cs
1 /*
2  VectSharp - A light library for C# vector graphics.
3  Copyright (C) 2020-2022 Giorgio Bianchini
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, version 3.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public License
15  along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17 
18 using System;
19 using System.Collections.Generic;
20 using System.Linq;
21 
22 namespace VectSharp
23 {
24  /// <summary>
25  /// Represents a point relative to an origin in the top-left corner.
26  /// </summary>
27  public struct Point
28  {
29  /// <summary>
30  /// Horizontal (x) coordinate, measured to the right of the origin.
31  /// </summary>
32  public double X;
33 
34  /// <summary>
35  /// Vertical (y) coordinate, measured to the bottom of the origin.
36  /// </summary>
37  public double Y;
38 
39  /// <summary>
40  /// Create a new <see cref="Point"/>.
41  /// </summary>
42  /// <param name="x">The horizontal (x) coordinate.</param>
43  /// <param name="y">The vertical (y) coordinate.</param>
44  public Point(double x, double y)
45  {
46  X = x;
47  Y = y;
48  }
49 
50  /// <summary>
51  /// Computes the modulus of the vector represented by the <see cref="Point"/>.
52  /// </summary>
53  /// <returns>The modulus of the vector represented by the <see cref="Point"/>.</returns>
54  public double Modulus()
55  {
56  return Math.Sqrt(X * X + Y * Y);
57  }
58 
59  /// <summary>
60  /// Normalises a <see cref="Point"/>.
61  /// </summary>
62  /// <returns>The normalised <see cref="Point"/>.</returns>
63  public Point Normalize()
64  {
65  double mod = Modulus();
66  return new Point(X / mod, Y / mod);
67  }
68 
69  /// <summary>
70  /// Checks whether this <see cref="Point"/> is equal to another <see cref="Point"/>, up to a specified tolerance.
71  /// </summary>
72  /// <param name="p2">The <see cref="Point"/> to compare.</param>
73  /// <param name="tolerance">The tolerance threshold.</param>
74  /// <returns><see langword="true"/> if both coordinates of the <see cref="Point"/>s are closer than <paramref name="tolerance"/> or if their relative difference (i.e. <c>(a - b) / (a + b) * 2</c>) is smaller than <paramref name="tolerance"/>. <see langword="false"/> otherwise.</returns>
75  public bool IsEqual(Point p2, double tolerance)
76  {
77  return (Math.Abs(p2.X - this.X) <= tolerance || Math.Abs((p2.X - this.X) / (p2.X + this.X)) <= tolerance * 0.5) && (Math.Abs(p2.Y - this.Y) <= tolerance || Math.Abs((p2.Y - this.Y) / (p2.Y + this.Y)) <= tolerance * 0.5);
78  }
79 
80  /// <summary>
81  /// Computes the top-left corner of the <see cref="Rectangle"/> identified by two <see cref="Point"/>s.
82  /// </summary>
83  /// <param name="p1">The first point.</param>
84  /// <param name="p2">The second point.</param>
85  /// <returns>A <see cref="Point"/> whose <see cref="X"/> coordinate is the smallest between the one of <paramref name="p1"/> and <paramref name="p2"/>, and likewise for the <see cref="Y"/> coordinate.</returns>
86  public static Point Min(Point p1, Point p2)
87  {
88  return new Point(Math.Min(p1.X, p2.X), Math.Min(p1.Y, p2.Y));
89  }
90 
91  /// <summary>
92  /// Computes the bottom-right corner of the <see cref="Rectangle"/> identified by two <see cref="Point"/>s.
93  /// </summary>
94  /// <param name="p1">The first point.</param>
95  /// <param name="p2">The second point.</param>
96  /// <returns>A <see cref="Point"/> whose <see cref="X"/> coordinate is the largest between the one of <paramref name="p1"/> and <paramref name="p2"/>, and likewise for the <see cref="Y"/> coordinate.</returns>
97  public static Point Max(Point p1, Point p2)
98  {
99  return new Point(Math.Max(p1.X, p2.X), Math.Max(p1.Y, p2.Y));
100  }
101 
102  /// <summary>
103  /// Computes the smallest <see cref="Rectangle"/> that contains all the specified points.
104  /// </summary>
105  /// <param name="points">The points whose bounds are being computed.</param>
106  /// <returns>The smallest <see cref="Rectangle"/> that contains all the specified points.</returns>
107  public static Rectangle Bounds(IEnumerable<Point> points)
108  {
109  bool initialised = false;
110  Point min = new Point(double.NaN, double.NaN);
111  Point max = new Point(double.NaN, double.NaN);
112 
113  foreach (Point pt in points)
114  {
115  if (!initialised)
116  {
117  min = pt;
118  max = pt;
119  initialised = true;
120  }
121  else
122  {
123  min = Point.Min(min, pt);
124  max = Point.Max(max, pt);
125  }
126  }
127 
128  return new Rectangle(min, max);
129  }
130 
131  /// <summary>
132  /// Computes the smallest <see cref="Rectangle"/> that contains all the specified points.
133  /// </summary>
134  /// <param name="points">The points whose bounds are being computed.</param>
135  /// <returns>The smallest <see cref="Rectangle"/> that contains all the specified points.</returns>
136  public static Rectangle Bounds(params Point[] points)
137  {
138  return Bounds((IEnumerable<Point>)points);
139  }
140  }
141 
142  /// <summary>
143  /// Represents the size of an object.
144  /// </summary>
145  public struct Size
146  {
147  /// <summary>
148  /// Width of the object.
149  /// </summary>
150  public double Width;
151 
152  /// <summary>
153  /// Height of the object.
154  /// </summary>
155  public double Height;
156 
157  /// <summary>
158  /// Create a new <see cref="Size"/>.
159  /// </summary>
160  /// <param name="width">The width of the object.</param>
161  /// <param name="height">The height of the object.</param>
162  public Size(double width, double height)
163  {
164  Width = width;
165  Height = height;
166  }
167  }
168 
169  /// <summary>
170  /// Represents a rectangle.
171  /// </summary>
172  public struct Rectangle
173  {
174  /// <summary>
175  /// A rectangle whose dimensions are all <see cref="double.NaN"/>.
176  /// </summary>
177  public static readonly Rectangle NaN = new Rectangle(double.NaN, double.NaN, double.NaN, double.NaN);
178 
179  /// <summary>
180  /// The top-left corner of the rectangle.
181  /// </summary>
182  public Point Location;
183 
184  /// <summary>
185  /// The size of the rectangle.
186  /// </summary>
187  public Size Size;
188 
189  /// <summary>
190  /// Create a new <see cref="Rectangle"/> given its top-left corner and its size.
191  /// </summary>
192  /// <param name="location">The top-left corner of the rectangle.</param>
193  /// <param name="size">The size of the rectangle.</param>
194  public Rectangle(Point location, Size size)
195  {
196  this.Location = location;
197  this.Size = size;
198  }
199 
200  /// <summary>
201  /// Create a new <see cref="Rectangle"/> given its top-left corner and its size.
202  /// </summary>
203  /// <param name="x">The horizontal coordinate of the top-left corner of the rectangle.</param>
204  /// <param name="y">The vertical coordinate of the top-left corner of the rectangle.</param>
205  /// <param name="width">The width of the rectangle.</param>
206  /// <param name="height">The height of the rectangle.</param>
207  public Rectangle(double x, double y, double width, double height)
208  {
209  Location = new Point(x, y);
210  Size = new Size(width, height);
211  }
212 
213  /// <summary>
214  /// Create a new <see cref="Rectangle"/> given its top-left corner and its bottom-right corner.
215  /// </summary>
216  /// <param name="topLeft">The top-left corner of the rectangle.</param>
217  /// <param name="bottomRight">The bottom-right corner of the rectangle.</param>
218  public Rectangle(Point topLeft, Point bottomRight)
219  {
220  this.Location = topLeft;
221  this.Size = new Size(bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y);
222  }
223 
224  /// <summary>
225  /// Computes the rectangular bounds of the union of two <see cref="Rectangle"/>s.
226  /// </summary>
227  /// <param name="rectangle1">The first <see cref="Rectangle"/>.</param>
228  /// <param name="rectangle2">The second <see cref="Rectangle"/>.</param>
229  /// <returns>The smallest <see cref="Rectangle"/> containing both <paramref name="rectangle1"/> and <paramref name="rectangle2"/>.</returns>
230  public static Rectangle Union(Rectangle rectangle1, Rectangle rectangle2)
231  {
232  double minX = rectangle1.Location.X;
233  double minY = rectangle1.Location.Y;
234  double maxX = rectangle1.Location.X;
235  double maxY = rectangle1.Location.Y;
236 
237  minX = Math.Min(minX, rectangle1.Location.X + rectangle1.Size.Width);
238  minX = Math.Min(minX, rectangle2.Location.X);
239  minX = Math.Min(minX, rectangle2.Location.X + rectangle2.Size.Width);
240 
241  minY = Math.Min(minY, rectangle1.Location.Y + rectangle1.Size.Height);
242  minY = Math.Min(minY, rectangle2.Location.Y);
243  minY = Math.Min(minY, rectangle2.Location.Y + rectangle2.Size.Height);
244 
245 
246  maxX = Math.Max(maxX, rectangle1.Location.X + rectangle1.Size.Width);
247  maxX = Math.Max(maxX, rectangle2.Location.X);
248  maxX = Math.Max(maxX, rectangle2.Location.X + rectangle2.Size.Width);
249 
250  maxY = Math.Max(maxY, rectangle1.Location.Y + rectangle1.Size.Height);
251  maxY = Math.Max(maxY, rectangle2.Location.Y);
252  maxY = Math.Max(maxY, rectangle2.Location.Y + rectangle2.Size.Height);
253 
254  return new Rectangle(minX, minY, maxX - minX, maxY - minY);
255  }
256 
257  /// <summary>
258  /// Computes the rectangular bounds of the union of multiple <see cref="Rectangle"/>s.
259  /// </summary>
260  /// <param name="rectangles">The <see cref="Rectangle"/>s whose union will be computed.</param>
261  /// <returns>The smallest <see cref="Rectangle"/> containing all the <paramref name="rectangles"/>.</returns>
262  public static Rectangle Union(IEnumerable<Rectangle> rectangles)
263  {
264  if (rectangles.Any())
265  {
266  bool initialised = false;
267 
268  Rectangle tbr = new Rectangle();
269 
270  foreach (Rectangle rect in rectangles)
271  {
272  if (!initialised)
273  {
274  tbr = rect;
275  }
276  else
277  {
278  tbr = Union(rect, tbr);
279  }
280  }
281 
282  return tbr;
283  }
284  else
285  {
286  return Rectangle.NaN;
287  }
288  }
289 
290  /// <summary>
291  /// Computes the rectangular bounds of the union of multiple <see cref="Rectangle"/>s.
292  /// </summary>
293  /// <param name="rectangles">The <see cref="Rectangle"/>s whose union will be computed.</param>
294  /// <returns>The smallest <see cref="Rectangle"/> containing all the <paramref name="rectangles"/>.</returns>
295  public static Rectangle Union(params Rectangle[] rectangles)
296  {
297  return Union((IEnumerable<Rectangle>)rectangles);
298  }
299  }
300 }
VectSharp.Rectangle
Represents a rectangle.
Definition: Point.cs:173
VectSharp.Size.Size
Size(double width, double height)
Create a new Size.
Definition: Point.cs:162
VectSharp.Rectangle.Rectangle
Rectangle(Point topLeft, Point bottomRight)
Create a new Rectangle given its top-left corner and its bottom-right corner.
Definition: Point.cs:218
VectSharp.Point.Min
static Point Min(Point p1, Point p2)
Computes the top-left corner of the Rectangle identified by two Points.
Definition: Point.cs:86
VectSharp.Rectangle.Union
static Rectangle Union(params Rectangle[] rectangles)
Computes the rectangular bounds of the union of multiple Rectangles.
Definition: Point.cs:295
VectSharp
Definition: Brush.cs:26
VectSharp.Size.Height
double Height
Height of the object.
Definition: Point.cs:155
VectSharp.Point.IsEqual
bool IsEqual(Point p2, double tolerance)
Checks whether this Point is equal to another Point, up to a specified tolerance.
Definition: Point.cs:75
VectSharp.Point.Modulus
double Modulus()
Computes the modulus of the vector represented by the Point.
Definition: Point.cs:54
VectSharp.Rectangle.Union
static Rectangle Union(IEnumerable< Rectangle > rectangles)
Computes the rectangular bounds of the union of multiple Rectangles.
Definition: Point.cs:262
VectSharp.Rectangle.Size
Size Size
The size of the rectangle.
Definition: Point.cs:187
VectSharp.Rectangle.Rectangle
Rectangle(Point location, Size size)
Create a new Rectangle given its top-left corner and its size.
Definition: Point.cs:194
VectSharp.Rectangle.NaN
static readonly Rectangle NaN
A rectangle whose dimensions are all double.NaN.
Definition: Point.cs:177
VectSharp.Point.Point
Point(double x, double y)
Create a new Point.
Definition: Point.cs:44
VectSharp.Point.X
double X
Horizontal (x) coordinate, measured to the right of the origin.
Definition: Point.cs:32
VectSharp.Point.Bounds
static Rectangle Bounds(params Point[] points)
Computes the smallest Rectangle that contains all the specified points.
Definition: Point.cs:136
VectSharp.Size
Represents the size of an object.
Definition: Point.cs:146
VectSharp.Rectangle.Rectangle
Rectangle(double x, double y, double width, double height)
Create a new Rectangle given its top-left corner and its size.
Definition: Point.cs:207
VectSharp.Rectangle.Location
Point Location
The top-left corner of the rectangle.
Definition: Point.cs:182
VectSharp.Size.Width
double Width
Width of the object.
Definition: Point.cs:150
VectSharp.Point.Normalize
Point Normalize()
Normalises a Point.
Definition: Point.cs:63
VectSharp.Point.Max
static Point Max(Point p1, Point p2)
Computes the bottom-right corner of the Rectangle identified by two Points.
Definition: Point.cs:97
VectSharp.Point
Represents a point relative to an origin in the top-left corner.
Definition: Point.cs:28
VectSharp.Rectangle.Union
static Rectangle Union(Rectangle rectangle1, Rectangle rectangle2)
Computes the rectangular bounds of the union of two Rectangles.
Definition: Point.cs:230
VectSharp.Point.Bounds
static Rectangle Bounds(IEnumerable< Point > points)
Computes the smallest Rectangle that contains all the specified points.
Definition: Point.cs:107
VectSharp.Point.Y
double Y
Vertical (y) coordinate, measured to the bottom of the origin.
Definition: Point.cs:37