ThinkGeo.com    |     Documentation    |     Premium Support

ShapeValidationResult Structure

Howard,


What does ShapeValidationResult.IsValid == true mean?    I ran a PointShape with lat/long outside the bounding box -180, 90, 180, -90 with my map unit set to DecimaDegrees yet ShapeValidationResult.IsValid was true.  I used the simple test.  Under what conditions is the result not valid?


Thanks,


Klaus



Hi Klaus, 
  
 BaseShape is actually a geometry; it doesn’t contain any spatial information. It can be a geometry in the screen coordinate and world coordinate too. So when your PointShape is outside of the bounding box, it’s still a valid point geometry. To find a invalid geometry, for example, the Rectangle exception you indicated before; if the UpperLeftPoint.X > LowerRightPoint.X, this rectangle will be invalid. 
  
 Hope it makes sense. 
  
 Thanks, 
 Howard

Klaus, 
  
   The IsValid does not know your points are decimal degrees as it is not provided anywhere.  The IsValid is just a very quick sanity check and is not a detailed validation system.  It test for things like Howard is saying such is if the rectangle is well formed.  In a near version we will have a more robust validation check. 
  
 David

 Got it guys, thanks.



Klaus, 
  
   Just responding back to take this off our radar. 
  
 David

 Sure.  thanks.



Hi Klaus, 
  
 You are welcome, just feel free to let us know if you have more queries. 
  
 Thanks, 
 Howard

Just a quick followup on this.


If one calls BaseShape.Buffer with an invalid geometry based on the map and distance unit, an exception is thrown for the invalid geometry coordinate.


I have a suggestion:  Create a TryBuffer version of Buffer that simply returns a bool out param with a value of false and the response buffer set to max geometry as specified by the unit and distance parameters, if the geometry is not valid.  You have all of this information to make this decision.  This will provide a simple validation system before you get a robust one in place.


 



Klaus,


Thanks for your post and suggestions. I understand what you are trying to do and I agree somehow with it, while, we need consider your suggestions more carefully to see if it is compatible with our APIs.
 
Now, we can just do a validation to make sure the shape is valid before doing buffer against it.

ShapeValidationResult result = baseShape.Validate(ShapeValidationMode.Simple);
if (result.IsValid)
{
    //Do buffer here.
}

 
Any more questions just feel free to let me know.
 
Thanks.
 
Yale

Klaus, 
  
   To add to that there are a few other things…  We cannot break compatibility with the API so we can’t change its current signature.  We could possibly add a new API but I think there are some other issues.  Another issue is that what you mentioned, passing back a true/false and have the real result passed back as a member variable, is the win32 way of doing things.  This way is used in the win32 internals where methods pass back a status and the real world result is in a parameter out.  They did this because there was no concept of an exception that bubbled up just failure.  The guidance from Microsoft is to not use that way for .NET and that raising exceptions is the preferred method to showing an error status.  The return parameter should be the work result of the function.  What Microsoft does say is to allow other methods to validate the chance that something can be completed without an error.  What they mean is that you should allow things like validate or ‘try this’ to allow the user to do things to be almost certain no error will occur.  We are working on that through more robust validation and that is really the only way we can move forward. 
  
 David

Guys, thanks for the response and I completely understand where you are coming from.   I am definitely not advocating breaking API compatibility.  I bring up this issue so that you can rethink your exception strategy in some cases as this issue has been brought up before.      I also do understand the philosophy behind Microsoft's approach of raising exceptions to report errors but you guys may be doing it too much, considering that raising of exceptions are typically more expensive than simply returning a true false in cases where one can easily recover.    



This particular case of throwing an exception when the map goes outside of valid extent, IMHO, is not necessarily.  I probably takes away resources that could be used to do other useful work, and provides no usefulness to the API.   I was catching these exceptions and showing a dialog box each time for info purposes and at one point, I had about 20 of these boxes open and had to shut down the app.   So the exceptions did not help here but stole away resources.  Also, MapClick and MouseMove event handling will be common scenarios so why would you expose data within these event arguments that is invalid, cannot easily be validated, and could easily cause exceptions to be thrown?  This must impact performance, no?



Again, maybe it is just a matter of documentation.  BaseShape.Validate(ShapeValidationMode) is great but it has passed most of the shapes i have run through it, so it is hard to see what exactly it does



Anyways, this is what I am doing to while waiting for better validation...Something like this would not be hard for you smart folks to quickly implement.  






 



 internal static EnhancedShapeValidationResult GetBuffer(BaseShape geom, double tolerance, GeographyUnit geoUnit, DistanceUnit distUnit)
        {            
            var result = new EnhancedShapeValidationResult();
            result.Shape = geom;

            var validation = geom.Validate(ShapeValidationMode.Simple);
            if (validation != null && validation.IsValid)
            {
                try
                {
                    result.Shape = geom.Buffer(tolerance, geoUnit, distUnit);
                    result.IsValid = true;
                    result.OriginalIsValid = true;
                }
                catch (Exception ex)
                {
                    // geometry is not valid
                    switch (geoUnit)
                    { 
                        case GeographyUnit.DecimalDegree:
                            result.Shape = ValidateShape(geom);
                            result.IsValid = true;
                            result.OriginalIsValid = false;
                            break;
                        default:
                            //result.Shape = ValidateShape(geom);
                            result.IsValid = false;
                            result.OriginalIsValid = false;
                            result.ValidationErrors = string.Format("Provided geometry for buffer operation is not valid. Validation for {0} not implemented.", geom.GetType().ToString());

                            //DialogBox.ShowExceptionModelessly(MessageBoxImage.Warning, string.Format( "Provided geometry for buffer operation is not valid. Validation for {0} not implemented.", geom.GetType().ToString()), ex);                    
                            break;
                    }                    
                }
            }
            
            return result;
        }

        #region Validations for Decimal Degrees

       public static BaseShape ValidateShape(BaseShape shape)
        {
            var point = shape as PointShape;
            if (point != null)            
                return ValidatePointShape(point);            


           // TODO:  Add other Shapes...
            return point;
        }

       public static PointShape ValidatePointShape(PointShape point)
        {            
            if (point != null)
            {
                if (point.X > 180)
                    point.X = 180;
                else if (point.X < -180)
                    point.X = -180;

                if (point.Y > 90)
                    point.Y = 90;
                else if (point.Y < -90)
                    point.Y = -90;
            }

            return point;
        }

       // TODO: Add nother shape validation methods

        #endregion

 public class EnhancedShapeValidationResult 
   {
       public BaseShape Shape { get; set; }
       public bool IsValid { get; set; }
       public bool OriginalIsValid { get; set; }
       public string ValidationErrors { get; set; }
   }


Klaus, 
  
   Thanks for the code snippet.  We have a strategy that we plan to employ when we get to the validation piece.  We consider incorporating your ideas along with that.  At this point we cannot add an API like this as it would not fit in with the other APIs.  Of course you have a nice alternate function you can call yourself in your application. :-)  Some of our clients write their own static helper classes to assist in their own special situations. 
  
 David