Advertisement
Guest User

dotSpatial - Extent Class

a guest
Mar 12th, 2012
289
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 28.35 KB | None | 0 0
  1. // ********************************************************************************************************
  2. // Product Name: DotSpatial.Data.dll
  3. // Description:  The data access libraries for the DotSpatial project.
  4. // ********************************************************************************************************
  5. // The contents of this file are subject to the MIT License (MIT)
  6. // you may not use this file except in compliance with the License. You may obtain a copy of the License at
  7. // http://dotspatial.codeplex.com/license
  8. //
  9. // Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
  10. // ANY KIND, either expressed or implied. See the License for the specific language governing rights and
  11. // limitations under the License.
  12. //
  13. // The Original Code is from MapWindow.dll version 6.0
  14. //
  15. // The Initial Developer of this Original Code is Ted Dunsford. Created 11/11/2009 2:34:48 PM
  16. //
  17. // Contributor(s): (Open source contributors should list themselves and their modifications here).
  18. //
  19. // ********************************************************************************************************
  20.  
  21. using System;
  22. using System.ComponentModel;
  23. using System.Diagnostics.Contracts;
  24. using System.Globalization;
  25. using DotSpatial.Serialization;
  26. using DotSpatial.Topology;
  27.  
  28. namespace DotSpatial.Data
  29. {
  30.     /// <summary>
  31.     /// Extent works like an envelope but is faster acting, has a minimum memory profile,
  32.     /// only works in 2D and has no events.
  33.     /// </summary>
  34.     [Serializable, TypeConverter(typeof(ExpandableObjectConverter))]
  35.     public class Extent : ICloneable, IExtent, IRectangle
  36.     {
  37.         /// <summary>
  38.         /// Creates a new instance of Extent.  This introduces no error checking and assumes
  39.         /// that the user knows what they are doing when working with this.
  40.         /// </summary>
  41.         public Extent()
  42.         {
  43.             MinX = double.MaxValue;
  44.             MaxX = double.MinValue;
  45.             MinY = double.MaxValue;
  46.             MaxY = double.MinValue;
  47.         }
  48.  
  49.         /// <summary>
  50.         /// Creates a new extent from the specified ordinates
  51.         /// </summary>
  52.         /// <param name="xMin"></param>
  53.         /// <param name="yMin"></param>
  54.         /// <param name="xMax"></param>
  55.         /// <param name="yMax"></param>
  56.         public Extent(double xMin, double yMin, double xMax, double yMax)
  57.         {
  58.             MinX = xMin;
  59.             MinY = yMin;
  60.             MaxX = xMax;
  61.             MaxY = yMax;
  62.         }
  63.  
  64.         /// <summary>
  65.         /// Given a long array of doubles, this builds an extent from a small part of that
  66.         /// xmin, ymin, xmax, ymax
  67.         /// </summary>
  68.         /// <param name="values"></param>
  69.         /// <param name="offset"></param>
  70.         public Extent(double[] values, int offset)
  71.         {
  72.             if (values.Length < 4 + offset)
  73.                 throw new IndexOutOfRangeException(
  74.                     "The length of the array of double values should be greater than or equal to 4 plus the value of the offset.");
  75.  
  76.             MinX = values[0 + offset];
  77.             MinY = values[1 + offset];
  78.             MaxX = values[2 + offset];
  79.             MaxY = values[3 + offset];
  80.         }
  81.  
  82.         /// <summary>
  83.         /// XMin, YMin, XMax, YMax order
  84.         /// </summary>
  85.         /// <param name="values"></param>
  86.         public Extent(double[] values)
  87.         {
  88.             if (values.Length < 4)
  89.                 throw new IndexOutOfRangeException("The length of the array of double values should be greater than or equal to 4.");
  90.  
  91.             MinX = values[0];
  92.             MinY = values[1];
  93.             MaxX = values[2];
  94.             MaxY = values[3];
  95.         }
  96.  
  97.         /// <summary>
  98.         /// Creates a new extent from the specified envelope
  99.         /// </summary>
  100.         /// <param name="env"></param>
  101.         public Extent(IEnvelope env)
  102.         {
  103.             if (Equals(env, null))
  104.                 throw new ArgumentNullException("env");
  105.  
  106.             MinX = env.Minimum.X;
  107.             MinY = env.Minimum.Y;
  108.             MaxX = env.Maximum.X;
  109.             MaxY = env.Maximum.Y;
  110.         }
  111.  
  112.         /// <summary>
  113.         /// Gets the Center of this extent.
  114.         /// </summary>
  115.         public Coordinate Center
  116.         {
  117.             get
  118.             {
  119.                 double x = MinX + (MaxX - MinX) / 2;
  120.                 double y = MinY + (MaxY - MinY) / 2;
  121.                 return new Coordinate(x, y);
  122.             }
  123.         }
  124.  
  125.         #region ICloneable Members
  126.  
  127.         /// <summary>
  128.         /// Produces a clone, rather than using this same object.
  129.         /// </summary>
  130.         /// <returns></returns>
  131.         public virtual object Clone()
  132.         {
  133.             return new Extent(MinX, MinY, MaxX, MaxY);
  134.         }
  135.  
  136.         #endregion
  137.  
  138.         #region IExtent Members
  139.  
  140.         /// <summary>
  141.         /// Gets or sets whether the M values are used.  M values are considered optional,
  142.         /// and not mandatory.  Unused could mean either bound is NaN for some reason, or
  143.         /// else that the bounds are invalid by the Min being less than the Max.
  144.         /// </summary>
  145.         public virtual bool HasM
  146.         {
  147.             get { return false; }
  148.         }
  149.  
  150.         /// <summary>
  151.         /// Gets or sets whether the M values are used.  M values are considered optional,
  152.         /// and not mandatory.  Unused could mean either bound is NaN for some reason, or
  153.         /// else that the bounds are invalid by the Min being less than the Max.
  154.         /// </summary>
  155.         public virtual bool HasZ
  156.         {
  157.             get { return false; }
  158.         }
  159.  
  160.         /// <summary>
  161.         /// Max X
  162.         /// </summary>
  163.         [Serialize("MaxX")]
  164.         public double MaxX { get; set; }
  165.  
  166.         /// <summary>
  167.         /// Max Y
  168.         /// </summary>
  169.         [Serialize("MaxY")]
  170.         public double MaxY { get; set; }
  171.  
  172.         /// <summary>
  173.         /// Min X
  174.         /// </summary>
  175.         [Serialize("MinX")]
  176.         public double MinX { get; set; }
  177.  
  178.         /// <summary>
  179.         /// Min Y
  180.         /// </summary>
  181.         [Serialize("MinY")]
  182.         public double MinY { get; set; }
  183.  
  184.         #endregion
  185.  
  186.         #region IRectangle Members
  187.  
  188.         /// <summary>
  189.         /// Gets MaxY - MinY.  Setting this will update MinY, keeping MaxY the same.  (Pinned at top left corner).
  190.         /// </summary>
  191.         public double Height
  192.         {
  193.             get { return MaxY - MinY; }
  194.             set { MinY = MaxY - value; }
  195.         }
  196.  
  197.         /// <summary>
  198.         /// Gets MaxX - MinX.  Setting this will update MaxX, keeping MinX the same. (Pinned at top left corner).
  199.         /// </summary>
  200.         public double Width
  201.         {
  202.             get { return MaxX - MinX; }
  203.             set { MaxX = MinX + value; }
  204.         }
  205.  
  206.         /// <summary>
  207.         /// Gets MinX.  Setting this will shift both MinX and MaxX, keeping the width the same.
  208.         /// </summary>
  209.         public double X
  210.         {
  211.             get { return MinX; }
  212.             set
  213.             {
  214.                 double w = Width;
  215.                 MinX = value;
  216.                 Width = w;
  217.             }
  218.         }
  219.  
  220.         /// <summary>
  221.         /// Gets MaxY.  Setting this will shift both MinY and MaxY, keeping the height the same.
  222.         /// </summary>
  223.         public double Y
  224.         {
  225.             get { return MaxY; }
  226.             set
  227.             {
  228.                 double h = Height;
  229.                 MaxY = value;
  230.                 Height = h;
  231.             }
  232.         }
  233.  
  234.         #endregion
  235.  
  236.         /// <summary>
  237.         /// Equality test
  238.         /// </summary>
  239.         /// <param name="left"></param>
  240.         /// <param name="right"></param>
  241.         /// <returns></returns>
  242.         public static bool operator ==(Extent left, IExtent right)
  243.         {
  244.             if (((object)left) == null) return ((right) == null);
  245.             return left.Equals(right);
  246.         }
  247.  
  248.         /// <summary>
  249.         /// Inequality test
  250.         /// </summary>
  251.         /// <param name="left"></param>
  252.         /// <param name="right"></param>
  253.         /// <returns></returns>
  254.         public static bool operator !=(Extent left, IExtent right)
  255.         {
  256.             if (((object)left) == null) return ((right) != null);
  257.             return !left.Equals(right);
  258.         }
  259.  
  260.         /// <summary>
  261.         /// Tests if this envelope is contained by the specified envelope
  262.         /// </summary>
  263.         /// <param name="ext"></param>
  264.         /// <returns></returns>
  265.         public virtual bool Contains(IExtent ext)
  266.         {
  267.             Contract.Requires(ext != null);
  268.  
  269.             if (Equals(ext, null))
  270.                 throw new ArgumentNullException("ext");
  271.  
  272.             if (MinX > ext.MinX)
  273.             {
  274.                 return false;
  275.             }
  276.             if (MaxX < ext.MaxX)
  277.             {
  278.                 return false;
  279.             }
  280.             if (MinY > ext.MinY)
  281.             {
  282.                 return false;
  283.             }
  284.             return !(MaxY < ext.MaxY);
  285.         }
  286.  
  287.         /// <summary>
  288.         /// Tests if this envelope is contained by the specified envelope
  289.         /// </summary>
  290.         /// <param name="c">The coordinate to test.</param>
  291.         /// <returns>Boolean</returns>
  292.         public virtual bool Contains(Coordinate c)
  293.         {
  294.             Contract.Requires(c != null, "c is null.");
  295.  
  296.             if (Equals(c, null))
  297.                 throw new ArgumentNullException("c");
  298.  
  299.             if (MinX > c.X)
  300.             {
  301.                 return false;
  302.             }
  303.             if (MaxX < c.X)
  304.             {
  305.                 return false;
  306.             }
  307.             if (MinY > c.Y)
  308.             {
  309.                 return false;
  310.             }
  311.             return !(MaxY < c.Y);
  312.         }
  313.  
  314.         /// <summary>
  315.         /// Tests if this envelope is contained by the specified envelope
  316.         /// </summary>
  317.         /// <param name="env"></param>
  318.         /// <returns></returns>
  319.         public virtual bool Contains(IEnvelope env)
  320.         {
  321.             Contract.Requires(env != null, "env is null.");
  322.  
  323.             if (Equals(env, null))
  324.                 throw new ArgumentNullException("env");
  325.  
  326.             if (MinX > env.Minimum.X)
  327.             {
  328.                 return false;
  329.             }
  330.             if (MaxX < env.Maximum.X)
  331.             {
  332.                 return false;
  333.             }
  334.             if (MinY > env.Minimum.Y)
  335.             {
  336.                 return false;
  337.             }
  338.             return !(MaxY < env.Maximum.Y);
  339.         }
  340.  
  341.         /// <summary>
  342.         /// Copies the MinX, MaxX, MinY, MaxY values from extent.
  343.         /// </summary>
  344.         /// <param name="extent">Any IExtent implementation.</param>
  345.         public virtual void CopyFrom(IExtent extent)
  346.         {
  347.             Contract.Requires(extent != null, "extent is null.");
  348.  
  349.             if (Equals(extent, null))
  350.                 throw new ArgumentNullException("extent");
  351.  
  352.             MinX = extent.MinX;
  353.             MaxX = extent.MaxX;
  354.             MinY = extent.MinY;
  355.             MaxY = extent.MaxY;
  356.         }
  357.  
  358.         /// <summary>
  359.         /// Allows equality testing for extents that is derived on the extent itself.
  360.         /// </summary>
  361.         /// <param name="obj"></param>
  362.         /// <returns></returns>
  363.         public override bool Equals(object obj)
  364.         {
  365.             // Check the identity case for reference equality
  366.             if (base.Equals(obj))
  367.             {
  368.                 return true;
  369.             }
  370.             IExtent other = obj as IExtent;
  371.             if (other == null)
  372.             {
  373.                 return false;
  374.             }
  375.             if (MinX != other.MinX)
  376.             {
  377.                 return false;
  378.             }
  379.             if (MaxX != other.MaxX)
  380.             {
  381.                 return false;
  382.             }
  383.             if (MinY != other.MinY)
  384.             {
  385.                 return false;
  386.             }
  387.             if (MaxY != other.MaxY)
  388.             {
  389.                 return false;
  390.             }
  391.             return true;
  392.         }
  393.  
  394.         /// <summary>
  395.         /// Expand will adjust both the minimum and maximum by the specified sizeX and sizeY
  396.         /// </summary>
  397.         /// <param name="padX">The amount to expand left and right.</param>
  398.         /// <param name="padY">The amount to expand up and down.</param>
  399.         public void ExpandBy(double padX, double padY)
  400.         {
  401.             MinX -= padX;
  402.             MaxX += padX;
  403.             MinY -= padY;
  404.             MaxY += padY;
  405.         }
  406.  
  407.         /// <summary>
  408.         /// This expand the extent by the specified padding on all bounds.  So the width will
  409.         /// change by twice the padding for instance.  To Expand only x and y, use
  410.         /// the overload with those values explicitly specified.
  411.         /// </summary>
  412.         /// <param name="padding">The double padding to expand the extent.</param>
  413.         public virtual void ExpandBy(double padding)
  414.         {
  415.             MinX -= padding;
  416.             MaxX += padding;
  417.             MinY -= padding;
  418.             MaxY += padding;
  419.         }
  420.  
  421.         /// <summary>
  422.         /// Expands this extent to include the domain of the specified extent
  423.         /// </summary>
  424.         /// <param name="ext">The extent to expand to include</param>
  425.         public virtual void ExpandToInclude(IExtent ext)
  426.         {
  427.             if (ext == null) //Simplify, avoiding nested if
  428.                 return;
  429.  
  430.             if (ext.MinX < MinX)
  431.             {
  432.                 MinX = ext.MinX;
  433.             }
  434.             if (ext.MinY < MinY)
  435.             {
  436.                 MinY = ext.MinY;
  437.             }
  438.             if (ext.MaxX > MaxX)
  439.             {
  440.                 MaxX = ext.MaxX;
  441.             }
  442.             if (ext.MaxY > MaxY)
  443.             {
  444.                 MaxY = ext.MaxY;
  445.             }
  446.  
  447.         }
  448.  
  449.         /// <summary>
  450.         /// Expands this extent to include the domain of the specified point
  451.         /// </summary>
  452.         /// <param name="x"></param>
  453.         /// <param name="y"></param>
  454.         public void ExpandToInclude(double x, double y)
  455.         {
  456.             if (x < MinX)
  457.             {
  458.                 MinX = x;
  459.             }
  460.             if (y < MinY)
  461.             {
  462.                 MinY = y;
  463.             }
  464.             if (x > MaxX)
  465.             {
  466.                 MaxX = x;
  467.             }
  468.             if (y > MaxY)
  469.             {
  470.                 MaxY = y;
  471.             }
  472.         }
  473.  
  474.         /// <summary>
  475.         /// Spreads the values for the basic X, Y extents across the whole range of int.
  476.         /// Repetition will occur, but it should be rare.
  477.         /// </summary>
  478.         /// <returns>Integer</returns>
  479.         public override int GetHashCode()
  480.         {
  481.             // 215^4 ~ Int.MaxValue so the value will cover the range based mostly on first 2 sig figs.
  482.             int xmin = Convert.ToInt32(MinX * 430 / MinX - 215);
  483.             int xmax = Convert.ToInt32(MaxX * 430 / MaxX - 215);
  484.             int ymin = Convert.ToInt32(MinY * 430 / MinY - 215);
  485.             int ymax = Convert.ToInt32(MaxY * 430 / MaxY - 215);
  486.             return (xmin * xmax * ymin * ymax);
  487.         }
  488.  
  489.         /// <summary>
  490.         /// Calculates the intersection of this extent and the other extent.  A result
  491.         /// with a min greater than the max in either direction is considered invalid
  492.         /// and represents no intersection.
  493.         /// </summary>
  494.         /// <param name="other">The other extent to intersect with.</param>
  495.         public virtual Extent Intersection(Extent other)
  496.         {
  497.             if (Equals(other, null))
  498.                 throw new ArgumentNullException("other");
  499.  
  500.             Extent result = new Extent
  501.             {
  502.                 MinX = (MinX > other.MinX) ? MinX : other.MinX,
  503.                 MaxX = (MaxX < other.MaxX) ? MaxX : other.MaxX,
  504.                 MinY = (MinY > other.MinY) ? MinY : other.MinY,
  505.                 MaxY = (MaxY < other.MaxY) ? MaxY : other.MaxY
  506.             };
  507.             return result;
  508.         }
  509.  
  510.         /// <summary>
  511.         /// Returns true if the coordinate exists anywhere within this envelope
  512.         /// </summary>
  513.         /// <param name="c"></param>
  514.         /// <returns></returns>
  515.         public virtual bool Intersects(Coordinate c)
  516.         {
  517.             if (Equals(c, null))
  518.                 throw new ArgumentNullException("c");
  519.  
  520.             if (double.IsNaN(c.X) || double.IsNaN(c.Y))
  521.             {
  522.                 return false;
  523.             }
  524.             return c.X >= MinX && c.X <= MaxX && c.Y >= MinY && c.Y <= MaxY;
  525.         }
  526.  
  527.         /// <summary>
  528.         /// Tests for intersection with the specified coordinate
  529.         /// </summary>
  530.         /// <param name="x">The double ordinate to test intersection with in the X direction</param>
  531.         /// <param name="y">The double ordinate to test intersection with in the Y direction</param>
  532.         /// <returns>True if a point with the specified x and y coordinates is within or on the border
  533.         /// of this extent object.  NAN values will always return false.</returns>
  534.         public bool Intersects(double x, double y)
  535.         {
  536.             if (double.IsNaN(x) || double.IsNaN(y))
  537.             {
  538.                 return false;
  539.             }
  540.             return x >= MinX && x <= MaxX && y >= MinY && y <= MaxY;
  541.         }
  542.  
  543.         /// <summary>
  544.         /// Tests to see if the point is inside or on the boundary of this extent.
  545.         /// </summary>
  546.         /// <param name="vert"></param>
  547.         /// <returns></returns>
  548.         public bool Intersects(Vertex vert)
  549.         {
  550.             if (vert.X < MinX)
  551.             {
  552.                 return false;
  553.             }
  554.             if (vert.X > MaxX)
  555.             {
  556.                 return false;
  557.             }
  558.             if (vert.Y < MinY)
  559.             {
  560.                 return false;
  561.             }
  562.             return !(vert.Y > MaxY);
  563.         }
  564.  
  565.         /// <summary>
  566.         /// Tests for an intersection with the specified extent
  567.         /// </summary>
  568.         /// <param name="ext">The other extent</param>
  569.         /// <returns>Boolean, true if they overlap anywhere, or even touch</returns>
  570.         public virtual bool Intersects(IExtent ext)
  571.         {
  572.             if (Equals(ext, null))
  573.                 throw new ArgumentNullException("ext");
  574.  
  575.             if (ext.MaxX < MinX)
  576.             {
  577.                 return false;
  578.             }
  579.             if (ext.MaxY < MinY)
  580.             {
  581.                 return false;
  582.             }
  583.             if (ext.MinX > MaxX)
  584.             {
  585.                 return false;
  586.             }
  587.             return !(ext.MinY > MaxY);
  588.         }
  589.  
  590.         /// <summary>
  591.         /// Tests with the specified envelope for a collision
  592.         /// </summary>
  593.         /// <param name="env"></param>
  594.         /// <returns></returns>
  595.         public virtual bool Intersects(IEnvelope env)
  596.         {
  597.             if (Equals(env, null))
  598.                 throw new ArgumentNullException("env");
  599.  
  600.             if (env.Maximum.X < MinX)
  601.             {
  602.                 return false;
  603.             }
  604.             if (env.Maximum.Y < MinY)
  605.             {
  606.                 return false;
  607.             }
  608.             if (env.Minimum.X > MaxX)
  609.             {
  610.                 return false;
  611.             }
  612.             return !(env.Minimum.Y > MaxY);
  613.         }
  614.  
  615.         /// <summary>
  616.         /// If this is undefined, it will have a min that is larger than the max, or else
  617.         /// any value is NaN.  This only
  618.         /// applies to the X and Z terms.  Check HasM or HasZ higher dimensions.
  619.         /// </summary>
  620.         /// <returns>Boolean, true if the envelope has not had values set for it yet.</returns>
  621.         public bool IsEmpty()
  622.         {
  623.             if (double.IsNaN(MinX) || double.IsNaN(MaxX))
  624.             {
  625.                 return true;
  626.             }
  627.             if (double.IsNaN(MinY) || double.IsNaN(MaxY))
  628.             {
  629.                 return true;
  630.             }
  631.             return (MinX > MaxX || MinY > MaxY); // Simplified
  632.         }
  633.  
  634.         /// <summary>
  635.         /// This allows parsing the X and Y values from a string version of the extent as:
  636.         /// 'X[-180|180], Y[-90|90]'  Where minimum always precedes maximum.  The correct
  637.         /// M or MZ version of extent will be returned if the string has those values.
  638.         /// </summary>
  639.         /// <param name="text">The string text to parse.</param>
  640.         public static Extent Parse(string text)
  641.         {
  642.             Extent result;
  643.             string fail;
  644.             if (TryParse(text, out result, out fail)) return result;
  645.             ExtentParseException ep = new ExtentParseException(String.Format("Attempting to read an extent string failed while reading the {0} term.", fail));
  646.             ep.Expression = text;
  647.             throw ep;
  648.         }
  649.  
  650.         /// <summary>
  651.         /// This reads the string and attempts to derive values from the text.
  652.         /// </summary>
  653.         /// <param name="text"></param>
  654.         /// <param name="result"></param>
  655.         /// <param name="nameFailed"></param>
  656.         /// <returns></returns>
  657.         public static bool TryParse(string text, out Extent result, out string nameFailed)
  658.         {
  659.             double xmin, xmax, ymin, ymax, mmin, mmax;
  660.             result = null;
  661.             if (text.Contains("Z"))
  662.             {
  663.                 //moved the declaration of zmin and zmax inside this scope, avoiding unncessary allocations
  664.                 //zmin and zmax are not used in other scopes
  665.                 double zmin, zmax;
  666.                 nameFailed = "Z";
  667.                 ExtentMZ mz = new ExtentMZ();
  668.                 if (TryExtract(text, "Z", out zmin, out zmax) == false) return false;
  669.                 mz.MinZ = zmin;
  670.                 mz.MaxZ = zmax;
  671.                 nameFailed = "M";
  672.                 if (TryExtract(text, "M", out mmin, out mmax) == false) return false;
  673.                 mz.MinM = mmin;
  674.                 mz.MaxM = mmax;
  675.                 result = mz;
  676.             }
  677.             else if (text.Contains("M"))
  678.             {
  679.                 nameFailed = "M";
  680.                 ExtentM me = new ExtentM();
  681.                 if (TryExtract(text, "M", out mmin, out mmax) == false) return false;
  682.                 me.MinM = mmin;
  683.                 me.MaxM = mmax;
  684.                 result = me;
  685.             }
  686.             else
  687.             {
  688.                 result = new Extent();
  689.             }
  690.             nameFailed = "X";
  691.             if (TryExtract(text, "X", out xmin, out xmax) == false) return false;
  692.             result.MinX = xmin;
  693.             result.MaxX = xmax;
  694.             nameFailed = "Y";
  695.             if (TryExtract(text, "Y", out ymin, out ymax) == false) return false;
  696.             result.MinY = ymin;
  697.             result.MaxY = ymax;
  698.             return true;
  699.         }
  700.  
  701.         /// <summary>
  702.         /// This centers the X and Y aspect of the extent on the specified center location.
  703.         /// </summary>
  704.         /// <param name="centerX"></param>
  705.         /// <param name="centerY"></param>
  706.         /// <param name="width"></param>
  707.         /// <param name="height"></param>
  708.         public void SetCenter(double centerX, double centerY, double width, double height)
  709.         {
  710.             MinX = centerX - width / 2;
  711.             MaxX = centerX + width / 2;
  712.             MinY = centerY - height / 2;
  713.             MaxY = centerY + height / 2;
  714.         }
  715.  
  716.         /// <summary>
  717.         /// This centers the X and Y aspect of the extent on the specified center location.
  718.         /// </summary>
  719.         /// <param name="center">The center coordinate to to set.</param>
  720.         /// <param name="width"></param>
  721.         /// <param name="height"></param>
  722.         public void SetCenter(Coordinate center, double width, double height)
  723.         {
  724.             SetCenter(center.X, center.Y, width, height);
  725.         }
  726.  
  727.         /// <summary>
  728.         /// This centers the extent on the specified coordinate, keeping the width and height the same.
  729.         /// </summary>
  730.         public void SetCenter(Coordinate center)
  731.         {
  732.             //prevents NullReferenceException when accessing center.X and center.Y
  733.             if (Equals(center, null))
  734.                 throw new ArgumentNullException("center");
  735.  
  736.             SetCenter(center.X, center.Y, Width, Height);
  737.         }
  738.  
  739.         /// <summary>
  740.         /// Sets the values for xMin, xMax, yMin and yMax.
  741.         /// </summary>
  742.         /// <param name="minX">The double Minimum in the X direction.</param>
  743.         /// <param name="minY">The double Minimum in the Y direction.</param>
  744.         /// <param name="maxX">The double Maximum in the X direction.</param>
  745.         /// <param name="maxY">The double Maximum in the Y direction.</param>
  746.         public void SetValues(double minX, double minY, double maxX, double maxY)
  747.         {
  748.             MinX = minX;
  749.             MinY = minY;
  750.             MaxX = maxX;
  751.             MaxY = maxY;
  752.         }
  753.  
  754.         /// <summary>
  755.         /// Creates a geometric envelope interface from this
  756.         /// </summary>
  757.         /// <returns></returns>
  758.         public IEnvelope ToEnvelope()
  759.         {
  760.             return new Envelope(MinX, MaxX, MinY, MaxY);
  761.         }
  762.  
  763.         /// <summary>
  764.         /// Creates a string that shows the extent.
  765.         /// </summary>
  766.         /// <returns>The string form of the extent.</returns>
  767.         public override string ToString()
  768.         {
  769.             return "X[" + MinX + "|" + MaxX + "], Y[" + MinY + "|" + MaxY + "]";
  770.         }
  771.  
  772.         /// <summary>
  773.         /// Tests if this envelope is contained by the specified envelope
  774.         /// </summary>
  775.         /// <param name="ext"></param>
  776.         /// <returns></returns>
  777.         public virtual bool Within(IExtent ext)
  778.         {
  779.             if (Equals(ext, null))
  780.                 throw new ArgumentNullException("ext");
  781.  
  782.             if (MinX < ext.MinX)
  783.             {
  784.                 return false;
  785.             }
  786.             if (MaxX > ext.MaxX)
  787.             {
  788.                 return false;
  789.             }
  790.             if (MinY < ext.MinY)
  791.             {
  792.                 return false;
  793.             }
  794.             return !(MaxY > ext.MaxY);
  795.         }
  796.  
  797.         /// <summary>
  798.         /// Tests if this envelope is contained by the specified envelope
  799.         /// </summary>
  800.         /// <param name="env"></param>
  801.         /// <returns></returns>
  802.         public virtual bool Within(IEnvelope env)
  803.         {
  804.             if (Equals(env, null))
  805.                 throw new ArgumentNullException("env");
  806.  
  807.             if (MinX < env.Minimum.X)
  808.             {
  809.                 return false;
  810.             }
  811.             if (MaxX > env.Maximum.X)
  812.             {
  813.                 return false;
  814.             }
  815.             if (MinY < env.Minimum.Y)
  816.             {
  817.                 return false;
  818.             }
  819.             return !(MaxY > env.Maximum.Y);
  820.         }
  821.  
  822.         /// <summary>
  823.         /// Attempts to extract the min and max from one element of text.  The element should be
  824.         /// formatted like X[1.5, 2.7] using an invariant culture.
  825.         /// </summary>
  826.         /// <param name="entireText"></param>
  827.         /// <param name="name">The name of the dimension, like X.</param>
  828.         /// <param name="min">The minimum that gets assigned</param>
  829.         /// <param name="max">The maximum that gets assigned</param>
  830.         /// <returns>Boolean, true if the parse was successful.</returns>
  831.         private static bool TryExtract(string entireText, string name, out double min, out double max)
  832.         {
  833.             int i = entireText.IndexOf(name);
  834.             i += name.Length + 1;
  835.             int j = entireText.IndexOf(']', i);
  836.             string vals = entireText.Substring(i, j - i);
  837.             return TryParseExtremes(vals, out min, out max);
  838.         }
  839.  
  840.         /// <summary>
  841.         /// This method converts the X and Y text into two doubles.
  842.         /// </summary>
  843.         /// <returns></returns>
  844.         private static bool TryParseExtremes(string numeric, out double min, out double max)
  845.         {
  846.             string[] res = numeric.Split('|');
  847.             max = double.NaN;
  848.             if (double.TryParse(res[0].Trim(), NumberStyles.Any,
  849.                 CultureInfo.InvariantCulture, out min) == false) return false;
  850.             if (double.TryParse(res[1].Trim(), NumberStyles.Any,
  851.                 CultureInfo.InvariantCulture, out max) == false) return false;
  852.             return true;
  853.         }
  854.     }
  855. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement