ThinkGeo.com    |     Documentation    |     Premium Support

Invalid WKT for Oracle

I have some problems with getting a valid WKT for oracle. For Oracle the exterior rings are oriented counterclockwise and the interior rings are oriented clockwise, see ora-13367.ora-code.com/ for more information.


When i draw a multipolygon (with two polygons) with map suite, the corresponding wkt is clockwise for both polygons which is not what oracle expects.


the wkt, i got is: MULTIPOLYGON(((0.527343749926594 45.2130035510123,1.71386718726143 45.1975222980759,1.60400390602672 44.4808302736197,0.703124999902124 44.355278206667,0.48339843743271 44.6373912295045,0.659179687408242 44.7779358913574,0.395507812444945 44.9336963847275,0.527343749926594 45.2130035510123)),((2.2851562496819 45.1665471528767,2.85644531210238 45.1665471528767,2.8124999996085 44.7467332352896,2.39501953091661 44.6686528673202,1.93359374973084 44.8402906464358,2.06542968721249 44.9492492616435,2.2851562496819 45.1665471528767))) 


 


is there anyway to make the wkt valid for an oracle use?


thanks in advance?



Sebastien,



We have a method to reverse the points of inner rings. Please see the code below:

foreach (RingShape ring in polygonShape.InnerRings)
{
    ring.ReversePoints();
}



The problem is that in current version, we didn't public the method to judge whether the ring shape is clockwise or not. We need to discuss it or enhance our API to fix this issue.



Please use the method above temporary and let you know our result then.



Thanks,

Howard



hello 
  
 If it is not possible to get the rotation from your api is it possible to get it using NetTopologySuite ? For example, is there a method to get the surface either negative or positive? 
  
 Actually if the user draw a shape clockwise in map suite, the wkt will be clockwise and if the user draw a shape counterclockwise the wkt will be counterclockwise?   
  
 thanks in advance 
 sebastien

Hi Sebastien,



Here is a method to help you know whether the RingShape is counter clockwise or not. If we know that, we can find whether the outer ring and inner rings is clockwise or not, then reverse the illegal one. 


Please let me if there is any misunderstanding.

/// <summary>
/// Tests whether a ring is oriented counter-clockwise.
/// </summary>
/// <returns>Returns true if ring is oriented counter-clockwise.
public static bool IsRingShapeCounterClockwise(RingShape ringShape)
{
    // check that this is a valid ring - if not, simply return a dummy decimalDegreesValue
    //if (pointsCount < 4) return false;

    // algorithm to check if a Ring is stored in CCW order
    // find highest point
    Vertex hightestPoint = new Vertex(double.MinValue, double.MinValue);
    int hightestPointNumber = 0;
    int count = ringShape.Vertices.Count;
    for (int i = 0; i < count; i++)
    {
        if (ringShape.Vertices[i].Y > hightestPoint.Y)
        {
            hightestPoint = ringShape.Vertices[i];
            hightestPointNumber = i;
        }
    }

    // find points on either side of highest
    int previousPointNumber = hightestPointNumber - 1;
    if (previousPointNumber < 0)
    {
        previousPointNumber = count - 2;
    }
    Vertex previousPoint = ringShape.Vertices[previousPointNumber];

    int nextPointNumber = hightestPointNumber + 1;
    if (nextPointNumber >= count)
    {
        nextPointNumber = 1;
    }
    Vertex nextPoint = ringShape.Vertices[nextPointNumber];

    // translate so that hip is at the origin.
    // This will not affect the area calculation, and will avoid
    // finite-accuracy errors (i.e very small features with very large coordinates)
    // This also simplifies the discriminant calculation.
    double prev2x = previousPoint.X - hightestPoint.X;
    double prev2y = previousPoint.Y - hightestPoint.Y;
    double next2x = nextPoint.X - hightestPoint.X;
    double next2y = nextPoint.Y - hightestPoint.Y;
    // compute cross-product of features hip->next and hip->prev
    // (e.g. area of parallelogram they enclose)
    double disc = next2x * prev2y - next2y * prev2x;
    // If disc is exactly 0, lines are collinear.  There are two possible cases:
    //    (1) the lines lie along the x axis in opposite directions
    //    (2) the line lie on top of one another
    //  (2) should never happen, so we're going to ignore it!
    //    (Might want to assert this)
    //  (1) is handled by checking if next is left of prev ==> CCW

    bool isCounterClockwise = false;

    if (disc == 0.0)
    {
        // poly is CCW if prev x is right of next x
        isCounterClockwise = previousPoint.X > nextPoint.X;
    }
    else
    {
        // if area is positive, points are ordered CCW
        isCounterClockwise = disc > 0.0;
    }

    return isCounterClockwise;
}



Thanks,

Howard