0

I am currently not able to figure out what is causing the abnormal shape when drawing a polygon onto the map as shown below.

Instead of being a complete polygon, there seems to be a triangle in the middle?

enter image description here

I am using SQL geometry library in a DotNet app to buffer given array of coordinates.

When I use SQLGeometry in SSMS the Polygon seems fine as shown below, however there seems to be an Island as circled red.

enter image description here

Here is a SQL query to generate it

DECLARE @distance float = 75; 
DECLARE @shape nvarchar(max) = 'POLYGON((32.4549866 -99.8079586,32.4548149 
-99.8075294,32.4544716 -99.8071861,32.4542999 -99.8066711,32.4542999 
-99.7998047,32.4541283 -99.7992897,32.4537849 -99.7989464,32.4536133 
-99.7984314,32.4536133 -99.7901917,32.4534416 -99.7896767,32.4530983 -99.7893333,32.4529266 -99.7888184,32.4530983 -99.7883034,32.4534416 -99.7879601,32.4537849 -99.7869301,32.4548149 -99.7865868,32.4551582 -99.7862434,32.4556732 -99.7860718,32.4570465 -99.7860718,32.4575615 -99.7859001,32.4577332 -99.7853851,32.4575615 -99.7848701,32.4565315 -99.7845268,32.4561882 -99.7841835,32.4551582 -99.7838402,32.4549866 -99.7833252,32.4551582 -99.7828102,32.4556732 -99.7826385,32.4561882 -99.7828102,32.4565315 -99.7831535,32.4570465 -99.7833252,32.4577332 -99.7833252,32.4582481 -99.7831535,32.4584198 -99.7826385,32.4584198 -99.7819519,32.4585915 -99.7814369,32.4589348 -99.7810936,32.4591064 -99.7805786,32.4591064 -99.779892,32.4592781 -99.779377,32.4597931 -99.7792053,32.4603081 -99.779377,32.4606514 -99.780407,32.4609947 -99.7807503,32.4611664 -99.7812653,32.4611664 -99.7826385,32.461338 -99.7831535,32.461853 -99.7833252,32.462368 -99.7831535,32.4625397 -99.7826385,32.4625397 -99.7805786,32.4627113 -99.7800636,32.4637413 -99.7797203,32.463913 -99.7792053,32.4637413 -99.7786903,32.463398 -99.778347,32.463398 -99.7780037,32.4644279 -99.7776604,32.4645996 -99.7771454,32.4644279 -99.7766304,32.463398 -99.7762871,32.4627113 -99.7756004,32.4625397 -99.7750854,32.4625397 -99.7743988,32.4627113 -99.7738838,32.4632263 -99.7737122,32.4645996 -99.7737122,32.4651146 -99.7735405,32.4652863 -99.7730255,32.4651146 -99.7725105,32.4645996 -99.7723389,32.463913 -99.7723389,32.463398 -99.7721672,32.4632263 -99.7716522,32.4632263 -99.7709656,32.463398 -99.7704506,32.463913 -99.7702789,32.4644279 -99.7704506,32.4654579 -99.7714806,32.4658012 -99.7714806,32.4659729 -99.7709656,32.4659729 -99.7675323,32.4661446 -99.7670174,32.4666595 -99.7668457,32.4671745 -99.7670174,32.4673462 -99.7675323,32.4673462 -99.768219,32.4675179 -99.768734,32.4680328 -99.7689056,32.4685478 -99.768734,32.4687195 -99.768219,32.4687195 -99.7668457,32.4688911 -99.7663307,32.4694061 -99.7661591,32.4699211 -99.7663307,32.4702644 -99.766674,32.4707794 -99.7668457,32.4712944 -99.766674,32.4714661 -99.7661591,32.4714661 -99.7654724,32.4716377 -99.7649574,32.4721527 -99.7647858,32.4728394 -99.7647858,32.4733543 -99.7649574,32.4736977 -99.7653008,32.474041 -99.7653008,32.4747276 -99.7646141,32.4748993 -99.7640991,32.4748993 -99.7634125,32.4747276 -99.7628975,32.4742126 -99.7627258,32.4736977 -99.7628975,32.4733543 -99.7632408,32.4728394 -99.7634125,32.4721527 -99.7634125,32.4716377 -99.7632408,32.4714661 -99.7627258,32.4714661 -99.7592926,32.4716377 -99.7587776,32.4721527 -99.758606,32.473526 -99.758606,32.474041 -99.7587776,32.4743843 -99.7591209,32.4747276 -99.7591209,32.4748993 -99.758606,32.4748993 -99.756546,32.4747276 -99.756031,32.4743843 -99.756031,32.474041 -99.757061,32.473526 -99.7572327,32.473011 -99.757061,32.4726677 -99.756031,32.4716377 -99.7556877,32.4709511 -99.7550011,32.4706078 -99.7539711,32.4700928 -99.7537994,32.4695778 -99.7539711,32.4694061 -99.7544861,32.4694061 -99.7551727,32.4692345 -99.7556877,32.4687195 -99.7558594,32.4680328 -99.7558594,32.4675179 -99.7556877,32.4673462 -99.7551727,32.4673462 -99.7517395,32.4671745 -99.7512245,32.4668312 -99.7512245,32.4666595 -99.7517395,32.4666595 -99.7531128,32.4664879 -99.7536278,32.4661446 -99.7536278,32.4659729 -99.7531128,32.4659729 -99.7503662,32.4658012 -99.7498512,32.4652863 -99.7496796,32.4645996 -99.7496796,32.4640846 -99.7495079,32.463913 -99.7489929,32.463913 -99.7476196,32.4637413 -99.7471046,32.4627113 -99.7467613,32.4625397 -99.7462463,32.4625397 -99.7455597,32.462368 -99.7450447,32.461338 -99.7447014,32.4611664 -99.7441864,32.4611664 -99.7428131,32.4609947 -99.7422981,32.4606514 -99.7422981,32.4603081 -99.7433281,32.4592781 -99.7436714,32.4591064 -99.7441864,32.4591064 -99.7455597,32.4589348 -99.7460747,32.4585915 -99.746418,32.4584198 -99.746933,32.4584198 -99.7476196,32.4582481 -99.7481346,32.4577332 -99.7483063,32.4563599 -99.7483063,32.4558449 -99.7481346,32.4556732 -99.7476196,32.4558449 -99.7471046,32.4561882 -99.7467613,32.4563599 -99.7462463,32.4561882 -99.7457314,32.4558449 -99.745388,32.4558449 -99.7450447,32.4568748 -99.7447014,32.4570465 -99.7441864,32.4570465 -99.7421265,32.4572182 -99.7416115,32.4577332 -99.7414398,32.4611664 -99.7414398,32.4616814 -99.7412682,32.461853 -99.7407532,32.4616814 -99.7402382,32.4611664 -99.7400665,32.4591064 -99.7400665,32.4585915 -99.7398949,32.4582481 -99.7395515,32.4572182 -99.7392082,32.4561882 -99.7381783,32.4556732 -99.7380066,32.4549866 -99.7380066,32.4544716 -99.7378349,32.4542999 -99.7373199,32.4542999 -99.7366333,32.4541283 -99.7361183,32.4537849 -99.735775,32.4534416 -99.734745,32.4524117 -99.7344017,32.4520683 -99.7333717,32.4515533 -99.7332001,32.4510384 -99.7333717,32.450695 -99.7337151,32.4503517 -99.7337151,32.4501801 -99.7332001,32.4501801 -99.7318268,32.4500084 -99.7313118,32.4489784 -99.7309685,32.4488068 -99.7304535,32.4488068 -99.7263336,32.4486351 -99.7258186,32.4481201 -99.725647,32.4474335 -99.725647,32.4469185 -99.7258186,32.4467468 -99.7263336,32.4469185 -99.7268486,32.4472618 -99.7271919,32.4474335 -99.7277069,32.4472618 -99.7282219,32.4467468 -99.7283936,32.4460602 -99.7283936,32.4455452 -99.7285652,32.4453735 -99.7290802,32.4453735 -99.7297668,32.4455452 -99.7302818,32.4458885 -99.7306252,32.4458885 -99.7309685,32.4448586 -99.7313118,32.4448586 -99.7316551,32.4458885 -99.7319984,32.4460602 -99.7325134,32.4458885 -99.7330284,32.4453735 -99.7332001,32.4446869 -99.7332001,32.4441719 -99.7333717,32.4438286 -99.7337151,32.4433136 -99.7338867,32.442627 -99.7338867,32.442112 -99.7340584,32.4419403 -99.7345734,32.4419403 -99.7366333,32.4417686 -99.7371483,32.4412537 -99.7373199,32.440567 -99.7373199,32.440052 -99.7374916,32.4397087 -99.7378349,32.4391937 -99.7380066,32.4385071 -99.7380066,32.4379921 -99.7381783,32.4378204 -99.7386932,32.4379921 -99.7392082,32.4385071 -99.7393799,32.4390221 -99.7392082,32.4393654 -99.7388649,32.4398804 -99.7386932,32.4403954 -99.7388649,32.440567 -99.7393799,32.4403954 -99.7398949,32.4398804 -99.7400665,32.4391937 -99.7400665,32.4386787 -99.7402382,32.4385071 -99.7407532,32.4385071 -99.7421265,32.4383354 -99.7426414,32.4362755 -99.7447014,32.4352455 -99.7450447,32.4349022 -99.7460747,32.4343872 -99.7462463,32.4337006 -99.7462463,32.4331856 -99.7460747,32.4321556 -99.7450447,32.4318123 -99.7450447,32.4316406 -99.7455597,32.4316406 -99.746933,32.431469 -99.747448,32.430954 -99.7476196,32.4295807 -99.7476196,32.4290657 -99.7477913,32.428894 -99.7483063,32.4290657 -99.7488213,32.4295807 -99.7489929,32.430954 -99.7489929,32.431469 -99.7491646,32.4316406 -99.7496796,32.4316406 -99.7510529,32.431469 -99.7515678,32.430439 -99.7519112,32.4302673 -99.7524261,32.4302673 -99.7544861,32.4300957 -99.7550011,32.4290657 -99.7553444,32.428894 -99.7558594,32.428894 -99.7572327,32.4287224 -99.7577477,32.4280357 -99.7584343,32.4275208 -99.758606,32.4268341 -99.758606,32.4263191 -99.7587776,32.4261475 -99.7592926,32.4263191 -99.7598076,32.4268341 -99.7599792,32.4275208 -99.7599792,32.4280357 -99.7601509,32.4282074 -99.7606659,32.4282074 -99.7613525,32.4280357 -99.7618675,32.4275208 -99.7620392,32.4247742 -99.7620392,32.4242592 -99.7622108,32.4239159 -99.7625542,32.4235725 -99.7625542,32.4232292 -99.7622108,32.4227142 -99.7620392,32.4221992 -99.7622108,32.4218559 -99.7625542,32.420826 -99.7628975,32.4204826 -99.7632408,32.4194527 -99.7635841,32.419281 -99.7640991,32.4194527 -99.7646141,32.4199677 -99.7647858,32.4204826 -99.7646141,32.420826 -99.7642708,32.4213409 -99.7640991,32.4234009 -99.7640991,32.4239159 -99.7642708,32.4240875 -99.7647858,32.4240875 -99.7654724,32.4242592 -99.7659874,32.4249458 -99.766674,32.4259758 -99.7670174,32.4263191 -99.7673607,32.4268341 -99.7675323,32.4295807 -99.7675323,32.4300957 -99.767704,32.4300957 -99.7680473,32.4295807 -99.768219,32.428894 -99.768219,32.4283791 -99.7683907,32.4282074 -99.7689056,32.4282074 -99.7702789,32.4283791 -99.7707939,32.428894 -99.7709656,32.4295807 -99.7709656,32.4300957 -99.7711372,32.431469 -99.7725105,32.4316406 -99.7730255,32.4316406 -99.7785187,32.431469 -99.7790337,32.4311256 -99.779377,32.4307823 -99.780407,32.430439 -99.7807503,32.4302673 -99.7812653,32.4302673 -99.7819519,32.430439 -99.7824669,32.430954 -99.7826385,32.431469 -99.7824669,32.4318123 -99.7814369,32.4321556 -99.7810936,32.4323273 -99.7805786,32.4323273 -99.779892,32.4324989 -99.779377,32.4328423 -99.779377,32.4331856 -99.780407,32.4337006 -99.7805786,32.4343872 -99.7805786,32.4349022 -99.7807503,32.4350739 -99.7812653,32.4350739 -99.7819519,32.4352455 -99.7824669,32.4359322 -99.7831535,32.4362755 -99.7831535,32.4364471 -99.7826385,32.4364471 -99.7812653,32.4366188 -99.7807503,32.4369621 -99.7807503,32.4371338 -99.7812653,32.4371338 -99.7833252,32.4373055 -99.7838402,32.4378204 -99.7840118,32.4383354 -99.7838402,32.4385071 -99.7833252,32.4385071 -99.7826385,32.4386787 -99.7821236,32.4390221 -99.7821236,32.4391937 -99.7826385,32.4391937 -99.7840118,32.4393654 -99.7845268,32.440052 -99.7852135,32.441082 -99.7855568,32.441082 -99.7859001,32.4403954 -99.7865868,32.4398804 -99.7867584,32.4378204 -99.7867584,32.4373055 -99.7869301,32.4373055 -99.7872734,32.4378204 -99.7874451,32.4391937 -99.7874451,32.4397087 -99.7876167,32.440052 -99.7879601,32.440567 -99.7881317,32.4419403 -99.7881317,32.4424553 -99.7883034,32.4427986 -99.7893333,32.4431419 -99.7896767,32.4433136 -99.7901917,32.4433136 -99.7936249,32.4434853 -99.7941399,32.4440002 -99.7943115,32.4445152 -99.7941399,32.4446869 -99.7936249,32.4446869 -99.7901917,32.4448586 -99.7896767,32.4452019 -99.7893333,32.4455452 -99.7883034,32.4462318 -99.7876167,32.4467468 -99.7874451,32.4472618 -99.7876167,32.4474335 -99.7881317,32.4474335 -99.7888184,32.4476051 -99.7893333,32.4481201 -99.789505,32.4508667 -99.789505,32.4513817 -99.7896767,32.4515533 -99.7901917,32.4515533 -99.7915649,32.451725 -99.7920799,32.4520683 -99.7924232,32.45224 -99.7929382,32.45224 -99.7984314,32.4520683 -99.7989464,32.451725 -99.7992897,32.4515533 -99.7998047,32.451725 -99.8003197,32.452755 -99.800663,32.4529266 -99.801178,32.4529266 -99.8073578,32.4530983 -99.8078728,32.4537849 -99.8085594,32.4542999 -99.8087311,32.4548149 -99.8086452,32.4549866 -99.8083878,32.4549866 -99.8079586))'; 

DECLARE @g geometry;    
SET @g = geometry::STGeomFromText(@shape, 4326).STBuffer(@distance * 0.00001).MakeValid();    
SELECT @g, @g.STBuffer(@distance * 0.00001).ToString();

This is the function written in C# that generates the coordinates for the Map

public double[][] BufferCoordinates(List<string> coordinates, float bufferDistance)
{
        try
        {

            var shapeString = $"POLYGON(({string.Join(',', coordinates)}))";
            var shape = new SqlChars(shapeString);

            var sqlGeometry = SqlGeometry.STGeomFromText(shape, spatialRefId); 
            
            var buffering = sqlGeometry.STBuffer(bufferDistance / bufferTolerance)                                            
                                        .ToString()
                                        .Replace("POLYGON ((", "")
                                        .Replace("))", "")
                                        .Split(',')
                                        .Select(c => c.Trim());

            var bufferedCoordinates = buffering
                                   .Select(c => c.Replace("(", "").Replace(")", "").Split(' '))
                                   .Where(c => c.Length > 1)
                                   .Select(c => new double[] { Convert.ToDouble(c[0]), Convert.ToDouble(c[1]) })
                                   .ToArray();

            return bufferedCoordinates;

        }
        catch (Exception ex)
        {
            _logger.LogError(ex.ToString());
        }
        throw new Exception("Failed to generate coordinates");
    }

One thing I noticed, when the original input coordinates are buffered I get two sets of coordinates?

Could it be due to presence of inner Island(s)? If yes then how can I avoid that?

2
  • I would try (1) in SQL call MakeValid before STBuffer - it is better to buffer a valid shape, operations on invalid ones can produce invalid result, (2) add the same MakeValid to C# code Commented Apr 22, 2023 at 1:09
  • Thanks @Michael for the suggestion. I tried both MakeValid() in SQL and C# code and it output the same results.
    – KJSR
    Commented Apr 24, 2023 at 8:39

1 Answer 1

0

I think what you're seeing is the result of the simple replace you're using to extract the coordinates. The "POLYGON ((" is good, but a polygon with a hole in it would include a set of parentheses, one for the outer ring and one for the inner ring. Therefore, your replacing of the beginning parentheses and ending parentheses is leaving a "), (" in the middle. For handling this, you could first get the LINESTRING of the exterior ring using STExteriorRing() and then use your replace method to remove the "LINESTRING (" and ")". However, this wouldn't accurately show that there is a small hole in the buffered area. You could try looping through the interior rings using STNumInteriorRing() and STInteriorRingN() and extracting coordinates from those to add to your array in the proper order (you'd have to look up the syntax of that in your DotNet library). However, I'm guessing if you are using a SQL Geometry Library in DotNet, it should just be able to form a polygon using a well-known-text (WKT) string of the polygon, which you already are creating before you start replacing text values. Hope that helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.