Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/DynamicDataDisplay/Common/DataRect.cs @ 13808

Last change on this file since 13808 was 12503, checked in by aballeit, 9 years ago

#2283 added GUI and charts; fixed MCTS

File size: 24.8 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Windows;
6using System.Diagnostics;
7using Microsoft.Research.DynamicDataDisplay.Common;
8using System.Windows.Markup;
9using System.Globalization;
10using System.ComponentModel;
11using Microsoft.Research.DynamicDataDisplay.Charts;
12
13namespace Microsoft.Research.DynamicDataDisplay
14{
15  /// <summary>
16  /// Describes a rectangle in viewport or data coordinates.
17  /// </summary>
18  [Serializable]
19  [ValueSerializer(typeof(DataRectSerializer))]
20  [TypeConverter(typeof(DataRectConverter))]
21  public struct DataRect : IEquatable<DataRect>, IFormattable
22  {
23    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
24    private double xMin;
25    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
26    private double yMin;
27    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
28    private double width;
29    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
30    private double height;
31
32    #region Ctors
33
34    /// <summary>
35    /// Initializes a new instance of the <see cref="DataRect"/> struct.
36    /// </summary>
37    /// <param name="rect">Source rect.</param>
38    public DataRect(Rect rect)
39    {
40      xMin = rect.X;
41      yMin = rect.Y;
42      width = rect.Width;
43      height = rect.Height;
44    }
45
46    /// <summary>
47    /// Initializes a new instance of the <see cref="DataRect"/> struct.
48    /// </summary>
49    /// <param name="size">The size.</param>
50    public DataRect(Size size)
51    {
52      if (size.IsEmpty)
53      {
54        this = emptyRect;
55      }
56      else
57      {
58        xMin = yMin = 0.0;
59        width = size.Width;
60        height = size.Height;
61      }
62    }
63
64    /// <summary>
65    /// Initializes a new instance of the <see cref="DataRect"/> struct.
66    /// </summary>
67    /// <param name="location">The location.</param>
68    /// <param name="size">The size.</param>
69    public DataRect(Point location, Size size)
70    {
71      if (size.IsEmpty)
72      {
73        this = emptyRect;
74      }
75      else
76      {
77        xMin = location.X;
78        yMin = location.Y;
79        width = size.Width;
80        height = size.Height;
81      }
82    }
83
84    /// <summary>
85    /// Initializes a new instance of the <see cref="DataRect"/> struct.
86    /// </summary>
87    /// <param name="point1">The point1.</param>
88    /// <param name="point2">The point2.</param>
89    public DataRect(Point point1, Point point2)
90    {
91      xMin = Math.Min(point1.X, point2.X);
92      yMin = Math.Min(point1.Y, point2.Y);
93      width = Math.Max((double)(Math.Max(point1.X, point2.X) - xMin), 0);
94      height = Math.Max((double)(Math.Max(point1.Y, point2.Y) - yMin), 0);
95    }
96
97    /// <summary>
98    /// Initializes a new instance of the <see cref="DataRect"/> struct.
99    /// </summary>
100    /// <param name="point">The point.</param>
101    /// <param name="vector">The vector.</param>
102    public DataRect(Point point, Vector vector) : this(point, point + vector) { }
103
104    /// <summary>
105    /// Initializes a new instance of the <see cref="DataRect"/> struct.
106    /// </summary>
107    /// <param name="xMin">The minimal x.</param>
108    /// <param name="yMin">The minimal y.</param>
109    /// <param name="width">The width.</param>
110    /// <param name="height">The height.</param>
111    public DataRect(double xMin, double yMin, double width, double height)
112    {
113      if ((width < 0) || (height < 0))
114        throw new ArgumentException(Strings.Exceptions.WidthAndHeightCannotBeNegative);
115
116      this.xMin = xMin;
117      this.yMin = yMin;
118      this.width = width;
119      this.height = height;
120    }
121
122    #endregion
123
124    #region Static
125
126    /// <summary>
127    /// Creates the DataRect from minimal and maximal 'x' and 'y' coordinates.
128    /// </summary>
129    /// <param name="xMin">The x min.</param>
130    /// <param name="yMin">The y min.</param>
131    /// <param name="xMax">The x max.</param>
132    /// <param name="yMax">The y max.</param>
133    /// <returns></returns>
134    public static DataRect Create(double xMin, double yMin, double xMax, double yMax)
135    {
136      DataRect rect = new DataRect(xMin, yMin, xMax - xMin, yMax - yMin);
137      return rect;
138    }
139
140    /// <summary>
141    /// Creates DataRect from the points.
142    /// </summary>
143    /// <param name="x1">The x1.</param>
144    /// <param name="y1">The y1.</param>
145    /// <param name="x2">The x2.</param>
146    /// <param name="y2">The y2.</param>
147    /// <returns></returns>
148    public static DataRect FromPoints(double x1, double y1, double x2, double y2)
149    {
150      return new DataRect(new Point(x1, y1), new Point(x2, y2));
151    }
152
153    /// <summary>
154    /// Creates DataRect from the size and coordinates of its center.
155    /// </summary>
156    /// <param name="center">The center.</param>
157    /// <param name="width">The width.</param>
158    /// <param name="height">The height.</param>
159    /// <returns></returns>
160    public static DataRect FromCenterSize(Point center, double width, double height)
161    {
162      DataRect rect = new DataRect(center.X - width / 2, center.Y - height / 2, width, height);
163      return rect;
164    }
165
166    /// <summary>
167    /// Creates DataRect from the size and coordinates of its center.
168    /// </summary>
169    /// <param name="center">The center.</param>
170    /// <param name="size">The size.</param>
171    /// <returns></returns>
172    public static DataRect FromCenterSize(Point center, Size size)
173    {
174      return FromCenterSize(center, size.Width, size.Height);
175    }
176
177    /// <summary>
178    /// Creates DataRect from coordinates of center and size.
179    /// </summary>
180    /// <param name="centerX">The center X.</param>
181    /// <param name="centerY">The center Y.</param>
182    /// <param name="width">The width.</param>
183    /// <param name="height">The height.</param>
184    /// <returns></returns>
185    public static DataRect FromCenterSize(double centerX, double centerY, double width, double height)
186    {
187      return FromCenterSize(new Point(centerX, centerY), width, height);
188    }
189
190    /// <summary>
191    /// Intersects with the specified rectangle.
192    /// </summary>
193    /// <param name="rect1">The rect1.</param>
194    /// <param name="rect2">The rect2.</param>
195    /// <returns></returns>
196    public static DataRect Intersect(DataRect rect1, DataRect rect2)
197    {
198      rect1.Intersect(rect2);
199      return rect1;
200    }
201
202    public static implicit operator DataRect(Rect rect)
203    {
204      return new DataRect(rect);
205    }
206
207    #endregion
208
209    /// <summary>
210    /// Converts to WPF rect.
211    /// </summary>
212    /// <returns></returns>
213    public Rect ToRect()
214    {
215      return new Rect(xMin, yMin, width, height);
216    }
217
218    /// <summary>
219    /// Intersects with the specified rect.
220    /// </summary>
221    /// <param name="rect">The rect.</param>
222    public void Intersect(DataRect rect)
223    {
224      if (!IntersectsWith(rect))
225      {
226        this = DataRect.Empty;
227        return;
228      }
229
230      DataRect res = new DataRect();
231
232      double x = Math.Max(this.XMin, rect.XMin);
233      double y = Math.Max(this.YMin, rect.YMin);
234      res.width = Math.Max((double)(Math.Min(this.XMax, rect.XMax) - x), 0.0);
235      res.height = Math.Max((double)(Math.Min(this.YMax, rect.YMax) - y), 0.0);
236      res.xMin = x;
237      res.yMin = y;
238
239      this = res;
240    }
241
242    /// <summary>
243    /// Intersects with the specified rect.
244    /// </summary>
245    /// <param name="rect">The rect.</param>
246    /// <returns></returns>
247    public bool IntersectsWith(DataRect rect)
248    {
249      if (IsEmpty || rect.IsEmpty)
250        return false;
251
252      return ((((rect.XMin <= this.XMax) && (rect.XMax >= this.XMin)) && (rect.YMax >= this.YMin)) && (rect.YMin <= this.YMax));
253    }
254
255    /// <summary>
256    /// Gets a value indicating whether this instance is empty.
257    /// </summary>
258    /// <value><c>true</c> if this instance is empty; otherwise, <c>false</c>.</value>
259    public bool IsEmpty
260    {
261      get { return width < 0 && height < 0; }
262    }
263
264    /// <summary>
265    /// Gets a value indicating whether this instance is empty horizontally.
266    /// </summary>
267    /// <value>
268    ///   <c>true</c> if this instance is empty horizontally; otherwise, <c>false</c>.
269    /// </value>
270    public bool IsEmptyX
271    {
272      get { return width < 0; }
273    }
274
275    /// <summary>
276    /// Gets a value indicating whether this instance is empty vertically.
277    /// </summary>
278    /// <value>
279    ///   <c>true</c> if this instance is empty vertically; otherwise, <c>false</c>.
280    /// </value>
281    public bool IsEmptyY
282    {
283      get { return height < 0; }
284    }
285
286    /// <summary>
287    /// Gets the minimal y coordinate.
288    /// </summary>
289    /// <value>The bottom.</value>
290    public double YMin
291    {
292      get { return yMin; }
293      set
294      {
295        if (this.IsEmpty)
296          throw new InvalidOperationException(Strings.Exceptions.CannotModifyEmptyDataRect);
297
298        yMin = value;
299      }
300    }
301
302    /// <summary>
303    /// Gets the maximal y value.
304    /// </summary>
305    /// <value>The top.</value>
306    public double YMax
307    {
308      get
309      {
310        if (IsEmpty)
311          return Double.PositiveInfinity;
312
313        return yMin + height;
314      }
315    }
316
317    /// <summary>
318    /// Gets the minimal x value.
319    /// </summary>
320    /// <value>The left.</value>
321    public double XMin
322    {
323      get { return xMin; }
324      set
325      {
326        if (this.IsEmpty)
327          throw new InvalidOperationException(Strings.Exceptions.CannotModifyEmptyDataRect);
328
329        xMin = value;
330      }
331    }
332
333    /// <summary>
334    /// Gets the maximal x value.
335    /// </summary>
336    /// <value>The right.</value>
337    public double XMax
338    {
339      get
340      {
341        if (IsEmpty)
342          return Double.PositiveInfinity;
343
344        return xMin + width;
345      }
346    }
347
348    /// <summary>
349    /// Gets or sets the location.
350    /// </summary>
351    /// <value>The location.</value>
352    public Point Location
353    {
354      get { return new Point(xMin, yMin); }
355      set
356      {
357        if (IsEmpty)
358          throw new InvalidOperationException(Strings.Exceptions.CannotModifyEmptyDataRect);
359
360        xMin = value.X;
361        yMin = value.Y;
362      }
363    }
364
365    /// <summary>
366    /// Gets the point with coordinates X max Y max.
367    /// </summary>
368    /// <value>The X max Y max.</value>
369    public Point XMaxYMax
370    {
371      get { return new Point(XMax, YMax); }
372    }
373
374    /// <summary>
375    /// Gets the point with coordinates X min Y min.
376    /// </summary>
377    /// <value>The X min Y min.</value>
378    public Point XMinYMin
379    {
380      get { return new Point(xMin, yMin); }
381    }
382
383    /// <summary>
384    /// Gets or sets the size.
385    /// </summary>
386    /// <value>The size.</value>
387    public Size Size
388    {
389      get
390      {
391        if (IsEmpty)
392          return Size.Empty;
393
394        return new Size(width, height);
395      }
396      set
397      {
398        if (value.IsEmpty)
399        {
400          this = emptyRect;
401        }
402        else
403        {
404          if (IsEmpty)
405            throw new InvalidOperationException(Strings.Exceptions.CannotModifyEmptyDataRect);
406
407          width = value.Width;
408          height = value.Height;
409        }
410      }
411    }
412
413    /// <summary>
414    /// Gets or sets the width.
415    /// </summary>
416    /// <value>The width.</value>
417    public double Width
418    {
419      get { return width; }
420      set
421      {
422        if (this.IsEmpty)
423          throw new InvalidOperationException(Strings.Exceptions.CannotModifyEmptyDataRect);
424        if (value < 0)
425          throw new ArgumentOutOfRangeException(Strings.Exceptions.DataRectSizeCannotBeNegative);
426
427        width = value;
428      }
429    }
430
431    /// <summary>
432    /// Gets or sets the height.
433    /// </summary>
434    /// <value>The height.</value>
435    public double Height
436    {
437      get { return height; }
438      set
439      {
440        if (this.IsEmpty)
441          throw new InvalidOperationException(Strings.Exceptions.CannotModifyEmptyDataRect);
442        if (value < 0)
443          throw new ArgumentOutOfRangeException(Strings.Exceptions.DataRectSizeCannotBeNegative);
444
445        height = value;
446      }
447    }
448
449    /// <summary>
450    /// Gets the horizontal range.
451    /// </summary>
452    /// <value>The horizontal range.</value>
453    public Range<double> HorizontalRange
454    {
455      get { return new Range<double>(xMin, XMax); }
456    }
457
458    /// <summary>
459    /// Gets the vertical range.
460    /// </summary>
461    /// <value>The vertical range.</value>
462    public Range<double> VerticalRange
463    {
464      get { return new Range<double>(yMin, YMax); }
465    }
466
467    private static readonly DataRect emptyRect = CreateEmptyRect();
468
469    /// <summary>
470    /// Gets the empty rectangle.
471    /// </summary>
472    /// <value>The empty.</value>
473    public static DataRect Empty
474    {
475      get { return DataRect.emptyRect; }
476    }
477
478    private static DataRect CreateEmptyRect()
479    {
480      DataRect rect = new DataRect();
481      rect.xMin = Double.PositiveInfinity;
482      rect.yMin = Double.PositiveInfinity;
483      rect.width = Double.NegativeInfinity;
484      rect.height = Double.NegativeInfinity;
485      return rect;
486    }
487
488    private static readonly DataRect infinite = new DataRect(Double.MinValue / 2, Double.MinValue / 2, Double.MaxValue, Double.MaxValue);
489    /// <summary>
490    /// Gets the infinite dataRect.
491    /// </summary>
492    /// <value>The infinite.</value>
493    public static DataRect Infinite
494    {
495      get { return infinite; }
496    }
497
498    #region Object overrides
499
500    /// <summary>
501    /// Indicates whether this instance and a specified object are equal.
502    /// </summary>
503    /// <param name="obj">Another object to compare to.</param>
504    /// <returns>
505    /// true if <paramref name="obj"/> and this instance are the same type and represent the same value; otherwise, false.
506    /// </returns>
507    public override bool Equals(object obj)
508    {
509      if (obj == null)
510        return false;
511
512      if (!(obj is DataRect))
513        return false;
514
515      DataRect other = (DataRect)obj;
516
517      return Equals(other);
518    }
519
520    /// <summary>
521    /// Returns the hash code for this instance.
522    /// </summary>
523    /// <returns>
524    /// A 32-bit signed integer that is the hash code for this instance.
525    /// </returns>
526    public override int GetHashCode()
527    {
528      if (IsEmpty)
529        return 0;
530
531      return xMin.GetHashCode() ^
532          width.GetHashCode() ^
533          yMin.GetHashCode() ^
534          height.GetHashCode();
535    }
536
537    /// <summary>
538    /// Returns the fully qualified type name of this instance.
539    /// </summary>
540    /// <returns>
541    /// A <see cref="T:System.String"/> containing a fully qualified type name.
542    /// </returns>
543    public override string ToString()
544    {
545      if (IsEmpty)
546        return "Empty";
547
548      return String.Format("({0:F};{1:F}) -> {2:F}*{3:F}", xMin, yMin, width, height);
549    }
550
551    /// <summary>
552    /// Implements the operator ==.
553    /// </summary>
554    /// <param name="rect1">The rect1.</param>
555    /// <param name="rect2">The rect2.</param>
556    /// <returns>The result of the operator.</returns>
557    public static bool operator ==(DataRect rect1, DataRect rect2)
558    {
559      return rect1.Equals(rect2);
560    }
561
562    /// <summary>
563    /// Implements the operator !=.
564    /// </summary>
565    /// <param name="rect1">The rect1.</param>
566    /// <param name="rect2">The rect2.</param>
567    /// <returns>The result of the operator.</returns>
568    public static bool operator !=(DataRect rect1, DataRect rect2)
569    {
570      return !rect1.Equals(rect2);
571    }
572
573    /// <summary>
574    /// Checks if sizes of specified rectangles are equal with eps ratio.
575    /// </summary>
576    /// <param name="rect1">The rect1.</param>
577    /// <param name="rect2">The rect2.</param>
578    /// <param name="eps">The eps.</param>
579    /// <returns></returns>
580    public static bool EqualsEpsSizes(DataRect rect1, DataRect rect2, double eps)
581    {
582      double least = 1 / (1 + eps);
583      double greatest = 1 + eps;
584
585      double widthRatio = rect1.width / rect2.width;
586      double heightRatio = rect1.height / rect2.height;
587
588      return least < widthRatio && widthRatio < greatest &&
589        least < heightRatio && heightRatio < greatest;
590    }
591
592    /// <summary>
593    /// Checks if rect1 is similar to rect2 with coefficient eps.
594    /// </summary>
595    /// <param name="rect1">The rect1.</param>
596    /// <param name="rect2">The rect2.</param>
597    /// <param name="eps">The eps.</param>
598    /// <returns></returns>
599    public static bool EqualEps(DataRect rect1, DataRect rect2, double eps)
600    {
601      double width = Math.Min(rect1.width, rect2.width);
602      double height = Math.Min(rect1.height, rect2.height);
603      return Math.Abs(rect1.xMin - rect2.xMin) < width * eps &&
604           Math.Abs(rect1.XMax - rect2.XMax) < width * eps &&
605           Math.Abs(rect1.yMin - rect2.yMin) < height * eps &&
606           Math.Abs(rect1.YMax - rect2.YMax) < height * eps;
607    }
608
609    #endregion
610
611    #region IEquatable<DataRect> Members
612
613    /// <summary>
614    /// Indicates whether the current object is equal to another object of the same type.
615    /// </summary>
616    /// <param name="other">An object to compare with this object.</param>
617    /// <returns>
618    /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
619    /// </returns>
620    public bool Equals(DataRect other)
621    {
622      if (this.IsEmpty)
623        return other.IsEmpty;
624
625      return xMin == other.xMin &&
626          width == other.width &&
627          yMin == other.yMin &&
628          height == other.height;
629    }
630
631    #endregion
632
633    /// <summary>
634    /// Determines whether this DataRect contains point with specified coordinates.
635    /// </summary>
636    /// <param name="x">The x coordinate of point.</param>
637    /// <param name="y">The y coordinate of point.</param>
638    /// <returns>
639    ///   <c>true</c> if contains point with specified coordinates; otherwise, <c>false</c>.
640    /// </returns>
641    public bool Contains(double x, double y)
642    {
643      if (this.IsEmpty)
644        return false;
645
646      return x >= xMin &&
647        x <= XMax &&
648        y >= yMin &&
649        y <= YMax;
650    }
651
652    /// <summary>
653    /// Determines whether rectangle contains the specified point.
654    /// </summary>
655    /// <param name="point">The point.</param>
656    /// <returns>
657    ///   <c>true</c> if [contains] [the specified point]; otherwise, <c>false</c>.
658    /// </returns>
659    public bool Contains(Point point)
660    {
661      return Contains(point.X, point.Y);
662    }
663
664    /// <summary>
665    /// Determines whether rectangle contains the specified rect.
666    /// </summary>
667    /// <param name="rect">The rect.</param>
668    /// <returns>
669    ///   <c>true</c> if [contains] [the specified rect]; otherwise, <c>false</c>.
670    /// </returns>
671    public bool Contains(DataRect rect)
672    {
673      if (this.IsEmpty || rect.IsEmpty)
674        return false;
675
676      return
677        this.xMin <= rect.xMin &&
678        this.yMin <= rect.yMin &&
679        this.XMax >= rect.XMax &&
680        this.YMax >= rect.YMax;
681    }
682
683    /// <summary>
684    /// Offsets at the specified vector.
685    /// </summary>
686    /// <param name="offsetVector">The offset vector.</param>
687    public void Offset(Vector offsetVector)
688    {
689      if (this.IsEmpty)
690        throw new InvalidOperationException(Strings.Exceptions.CannotModifyEmptyDataRect);
691
692      this.xMin += offsetVector.X;
693      this.yMin += offsetVector.Y;
694    }
695
696    /// <summary>
697    /// Offsets at the specified offset.
698    /// </summary>
699    /// <param name="offsetX">The offset X.</param>
700    /// <param name="offsetY">The offset Y.</param>
701    public void Offset(double offsetX, double offsetY)
702    {
703      if (this.IsEmpty)
704        throw new InvalidOperationException(Strings.Exceptions.CannotModifyEmptyDataRect);
705
706      this.xMin += offsetX;
707      this.yMin += offsetY;
708    }
709
710    /// <summary>
711    /// Offsets the specified rect at values.
712    /// </summary>
713    /// <param name="rect">The rect.</param>
714    /// <param name="offsetX">The offset X.</param>
715    /// <param name="offsetY">The offset Y.</param>
716    /// <returns></returns>
717    public static DataRect Offset(DataRect rect, double offsetX, double offsetY)
718    {
719      rect.Offset(offsetX, offsetY);
720      return rect;
721    }
722
723    internal void UnionFinite(DataRect rect)
724    {
725      if (!rect.IsEmpty)
726      {
727        if (rect.xMin.IsInfinite())
728          rect.xMin = 0;
729        if (rect.yMin.IsInfinite())
730          rect.yMin = 0;
731        if (rect.width.IsInfinite())
732          rect.width = 0;
733        if (rect.height.IsInfinite())
734          rect.height = 0;
735      }
736
737      Union(rect);
738    }
739
740    /// <summary>
741    /// Unions with the specified rect.
742    /// </summary>
743    /// <param name="rect">The rect.</param>
744    public void Union(DataRect rect)
745    {
746      if (IsEmpty)
747      {
748        this = rect;
749        return;
750      }
751      else if (!rect.IsEmpty)
752      {
753        double minX = Math.Min(xMin, rect.xMin);
754        double minY = Math.Min(yMin, rect.yMin);
755
756        if (rect.width == Double.PositiveInfinity || this.width == Double.PositiveInfinity)
757        {
758          this.width = Double.PositiveInfinity;
759        }
760        else
761        {
762          double maxX = Math.Max(XMax, rect.XMax);
763          this.width = Math.Max(maxX - minX, 0.0);
764        }
765
766        if (rect.height == Double.PositiveInfinity || this.height == Double.PositiveInfinity)
767        {
768          this.height = Double.PositiveInfinity;
769        }
770        else
771        {
772          double maxY = Math.Max(YMax, rect.YMax);
773          this.height = Math.Max(maxY - minY, 0.0);
774        }
775
776        this.xMin = minX;
777        this.yMin = minY;
778      }
779    }
780
781    /// <summary>
782    /// Unions rect with the specified point.
783    /// </summary>
784    /// <param name="point">The point.</param>
785    public void Union(Point point)
786    {
787      this.Union(new DataRect(point, point));
788    }
789
790    /// <summary>
791    /// Unions rect with specified x-coordinate.
792    /// </summary>
793    /// <param name="x">The x.</param>
794    public void UnionX(double x)
795    {
796      if (Double.IsInfinity(xMin)) // empty
797      {
798        xMin = x;
799      }
800      else if (xMin < x)
801      {
802        width = Math.Max(width, x - xMin);
803      }
804      else // xMin > x
805      {
806        width += xMin - x;
807        xMin = x;
808      }
809    }
810
811    /// <summary>
812    /// Unions rect with specified x-coordinate.
813    /// </summary>
814    /// <param name="rect">The rect.</param>
815    /// <param name="x">The x.</param>
816    /// <returns></returns>
817    public static DataRect UnionX(DataRect rect, double x)
818    {
819      rect.UnionX(x);
820      return rect;
821    }
822
823    /// <summary>
824    /// Unions rect with specified y-coordinate.
825    /// </summary>
826    /// <param name="y">The y.</param>
827    public void UnionY(double y)
828    {
829      if (Double.IsInfinity(yMin)) // empty
830      {
831        yMin = y;
832      }
833      else if (yMin < y)
834      {
835        height = Math.Max(height, y - yMin);
836      }
837      else // yMin > y
838      {
839        height += yMin - y;
840        yMin = y;
841      }
842    }
843
844    /// <summary>
845    /// Unions rect with specified y-coordinate.
846    /// </summary>
847    /// <param name="rect">The rect.</param>
848    /// <param name="y">The y.</param>
849    /// <returns></returns>
850    public static DataRect UnionY(DataRect rect, double y)
851    {
852      rect.UnionY(y);
853      return rect;
854    }
855
856    /// <summary>
857    /// Unions with the specified rect.
858    /// </summary>
859    /// <param name="rect">The rect.</param>
860    /// <param name="point">The point.</param>
861    /// <returns></returns>
862    public static DataRect Union(DataRect rect, Point point)
863    {
864      rect.Union(point);
865
866      return rect;
867    }
868
869    /// <summary>
870    /// Unions with the specified rect.
871    /// </summary>
872    /// <param name="rect1">The rect1.</param>
873    /// <param name="rect2">The rect2.</param>
874    /// <returns></returns>
875    public static DataRect Union(DataRect rect1, DataRect rect2)
876    {
877      rect1.Union(rect2);
878
879      return rect1;
880    }
881
882    internal string ConvertToString(string format, IFormatProvider provider)
883    {
884      if (IsEmpty)
885        return "Empty";
886
887      char listSeparator = TokenizerHelper.GetNumericListSeparator(provider);
888      return String.Format(provider, "{1:" + format + "}{0}{2:" + format + "}{0}{3:" + format + "}{0}{4:" + format + "}", listSeparator, xMin, yMin, width, height);
889    }
890
891    /// <summary>
892    /// Parses the specified string as a DataRect.
893    /// </summary>
894    /// <remarks>
895    /// There are three possible string patterns, that are recognized as string representation of DataRect:
896    /// 1) Literal string "Empty" - represents an DataRect.Empty rect;
897    /// 2) String in format "d,d,d,d", where d is a floating-point number with '.' as decimal separator - is considered as a string
898    /// of "XMin,YMin,Width,Height";
899    /// 3) String in format "d,d d,d", where d is a floating-point number with '.' as decimal separator - is considered as a string
900    /// of "XMin,YMin XMax,YMax".
901    /// </remarks>
902    /// <param name="source">The source.</param>
903    /// <returns>DataRect, parsed from the given input string.</returns>
904    public static DataRect Parse(string source)
905    {
906      DataRect rect;
907      IFormatProvider cultureInfo = CultureInfo.GetCultureInfo("en-us");
908
909      if (source == "Empty")
910      {
911        rect = DataRect.Empty;
912      }
913      else
914      {
915        // format X,Y,Width,Height
916        string[] values = source.Split(',');
917        if (values.Length == 4)
918        {
919          rect = new DataRect(
920            Convert.ToDouble(values[0], cultureInfo),
921            Convert.ToDouble(values[1], cultureInfo),
922            Convert.ToDouble(values[2], cultureInfo),
923            Convert.ToDouble(values[3], cultureInfo)
924            );
925        }
926        else
927        {
928          // format XMin, YMin - XMax, YMax
929          values = source.Split(new Char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
930          rect = DataRect.Create(
931            Convert.ToDouble(values[0], cultureInfo),
932            Convert.ToDouble(values[1], cultureInfo),
933            Convert.ToDouble(values[2], cultureInfo),
934            Convert.ToDouble(values[3], cultureInfo)
935            );
936        }
937      }
938
939      return rect;
940    }
941
942    #region IFormattable Members
943
944    /// <summary>
945    /// Returns a <see cref="System.String"/> that represents this instance.
946    /// </summary>
947    /// <param name="format">The format.</param>
948    /// <param name="formatProvider">The format provider.</param>
949    /// <returns>
950    /// A <see cref="System.String"/> that represents this instance.
951    /// </returns>
952    string IFormattable.ToString(string format, IFormatProvider formatProvider)
953    {
954      return ConvertToString(format, formatProvider);
955    }
956
957    #endregion
958  }
959}
Note: See TracBrowser for help on using the repository browser.