Home - General / All posts - How can I calculate the max. width/length of an area?
 klausk115 post(s) #03-Aug-16 13:51 Hi,I am interested in the max. width/length of an area? How can I get it?thx
 tjhb10,093 post(s) #03-Aug-16 16:48 I think via the EnclosingCircle or EnclosingRectangle function, in the first case taking the its length (circumference) / pi, in the second finding one of the longest sides and taking its length.The first would be a very slight approximation (not a true circle), the second perhaps better.I'd have to check these work out in practice. Post sample data if you want to--not completely necessary though.
 Sloots678 post(s) #03-Aug-16 19:52 Is this what you want?SELECT RectWidth([ID]) as rwidth , RectHeight([ID]) as rheightFROM [Drawing] http://www.mppng.nl/manifold/pointlabeler
 tjhb10,093 post(s) #03-Aug-16 20:14 That is measured horizontally and vertically (as you know). I think what is wanted is maximum dimension.
 artlembo3,397 post(s) #03-Aug-16 21:11 If you want to find the farthest distance between any two vertices in an area, then you can:Assume you have a Drawing called D, with a unique ID for each area called polyid1. Use the Transform Tool to create "Points" for your area features2. Issue the following SQLSELECT max(dist), A_IDFROM  (SELECT  distance(A.[geom (i)], B.[Geom (i)]) AS dist, A.polyid AS A_ID  FROM D AS A, D AS B )GROUP BY A_ID
 tonyw736 post(s) #03-Aug-16 22:13 Interesting exercise. Attached is a map with two arbitrarily drawn demo areas. The two areas are identical. On the left side I tried an enclosing circle and notice the circle draws to touch three points along the edge of the area. On the right I used enclosing rectangle. On both I drew lines using snap-to between the vertices that my eyeball showed to be the furthest apart. The rectangle revealed the max length immediately if we define it as the longest distance between two vertices. Otherwise max length is the long side of the rectangle which is shorter than the 830.35 m long blue line. On the circle the two lines were visually similar in length and the intrinsic confirmed the longest line is the upper one at 830.35 m. klausk, what is the shape of your area and how are you defining maximum width? What is the purpose for determining a maximum width? Is maximum width the dimension perpendicular to the longest length or the width of the enclosing rectangle which in my totally arbitrary example the width of the enclosing rectangle is not perpendicular to maximum length? Attachments: Demo Area dimensions.map
 klausk115 post(s) #04-Aug-16 17:39 yes tony that is the information, which I would get. Is it possible to do this via script?
 tonyw736 post(s) #04-Aug-16 18:06 Hi KlausKHow many areas do you have? Others are really good at writing scripts, not me. I used to program (Fortran, Basic, dBase) but those days are behind me. Maybe ArtLembo? Do you have a manageable number of areas that you could do the 2-step process manually? 1. Select each area and add enclosing rectangle2. Visually see which two vertices are the furthest apart and using snap-to-area draw a line between those two vertices.The Table for the drawing will have the lengths of the lines which you can then use.
 artlembo3,397 post(s) #04-Aug-16 19:10 That is exactly what my query above does. It finds the max distance between the vertices in an area feature. From there, it would be very easy to then just divide by the area of the feature. I could probably work this out a little more if you contacted me off-line and gave me a little more background into what you're trying to do.
 tjhb10,093 post(s) #05-Aug-16 04:01 Tony's examples showed that (a) my suggestions were wrong and (b) Art's suggestion is right.(a) Since what do EnclosingRectangle and EnclosingCircle do? They find the minimum rectangle/circle which includes all vertices in the source geometry. That "minimum" is (often, and in principle) incompatible with drawing the longest possible axis from one vertex to another.(b) Which is exactly what Art's SQL does. However, it currently does it very inefficiently, in two ways.Here's an SQL exercise. What are those two ways?(And for Klaus, the objective here is an UPDATE query that writes the maximum width for each area into a column called, e.g., Length.)
 klausk115 post(s) #05-Aug-16 20:15 I am a starter in Mfd-SQL and have really no idea
 artlembo3,397 post(s) #05-Aug-16 21:39 That was a quick and dirty SQL example. It can be done elegantly with SQL, but I'd likely write a script to do 3 things:1. Use the Points transform2. Create the SQL above to get the max length 3. Write another SQL script that does the UPDATE.
 artlembo3,397 post(s) #05-Aug-16 23:29 OK, I did it all in SQL (again, Manifold continues to amaze me). Going to have to do a blog post on this one :-)UPDATE  (SELECT D.polyid, distratio, d.[Area (I)], dist  FROM  (SELECT max(distance(a.pt, b.pt)) as dist, a.polyid as polyid  FROM (SELECT polyid, NewPoint(centroidX([Coord]), centroidY([coord])) as pt, distratio  FROM D  SPLIT BY Coords(id) AS [Coord]   ) AS A, (SELECT polyid, NewPoint(centroidX([Coord]), centroidY([coord])) as pt, distratio  FROM D  SPLIT BY Coords(id) AS [Coord]     ) AS B WHERE a.polyid = b.polyid GROUP BY a.polyid) AS C, D WHERE d.polyid = c.polyid )SET distratio = [Area (I)]/distassume you have a Drawing called D, with a unique ID called polyid, and a field called distratio that you need to update. It's as simple as this. I think there is probably a way to simplify this, and make the SQL more terse, but I did it this way out of a stream of consciousness. Took all of 4 minutes to write. I think if I spent more time, I could make the SQL shorter, but I figure, why bother - this seems to work.Now the big question: How do you do this with traditional GIS??If you want to learn more SQL tricks like this, try my spatial SQL course here.Also, Introduction to Manifold 8, and Manifold Scripting.
 artlembo3,397 post(s) #05-Aug-16 23:48 Sorry, I performed a calculation which was the ratio of distance to area. If you don't want to do that just simply make the new value equal to the distance
 tjhb10,093 post(s) #10-Aug-16 02:07 Art has incorporated one of the optimizations I was thinking of above, and in the process also fixed a bug. The bug was that the earlier query found, for each point on the boundary of area A, not the farthest point also on the boundary of A (which is what we want, to give the width), but the farthest point on the boundary of any area. Joining on matching [polyid] fixes this--and of course, speeds things up, since fewer lengths are calculated.In the PostGIS version on his blog, Art has also made the other optimization I was thinking of--only testing points on the convex hull of each area. This is enough since we know that the farthest pair of points must lie on the convex hull. We can do this in Manifold syntax as well as in PostGIS.There is at least one more optimization we can make. Currently, each distance is tested twice--once from point P to point Q, and again from Q to P. In Manifold syntax we can avoid this by adding a second join condition (sticking with Art's comma form of join):...FROM(SELECT...) AS A,(SELECT...) AS BWHERE A.polyid = B.polyidAND A.pt < B.pt...We can do this because Manifold allows direct comparison of metrics (presumably via a unique hash), such that unless two metrics are identical, they can always be uniquely (though arbitrarily) ordered. So requiring that A.pt < B.pt means that each pair of points is only tested once. It also means that distances are not measured between each point and itself, which is also a nice improvement though probably less important.I would prefer to use a separate query to list the boundary points (or the boundary points of each convex hull), and call this from a second query, rather than repeat the same subquery twice. This ought to be faster, even though Manifold is likely to partly optimize the repetition for us.
 tjhb10,093 post(s) #10-Aug-16 08:11 Sorry for missing this but Art's current query still has a problem (hasty reading on both our parts).In the two inner queries (which are the same) we have the [Coord] column, produced by SPLIT BY, which holds a point for each source vertex, each on a separate row.Now the expressionNewPoint(centroidX([Coord]), centroidY([coord])) as ptis used to draw a new point at each of these points. First, this is unnecessary, since the new point [pt] is the same as the [Coord] it is made from. Or almost the same, since secondly, the new point is raw geometry, made from X and Y values, without a coordinate system. AssignCoordSys() would be required for the result here, else the copied points would be misplaced. (If they were necessary.)Anyway Klaus is left without something he can use, so I'm posting a tested revision.In advance, the source drawing named [Drawing] has a target floating-point column named [width]. (Create that column, adjusting names as needed.)There are two queries.[Query 1] lists the vertices of the convex hull of each source area.SELECT [ID], [Coord]FROM [Drawing]WHERE IsArea([ID])SPLIT BY Coords(ConvexHull([ID])) AS [Coord];[Query 2] calls [Query 1] twice, finds the farthest pair of vertices for each source area, joins back to the source (necessary because we are finding an aggregate), and writes the result to the target column [width].UPDATE    (SELECT        [D].[width],        [V].[w]    FROM        [Drawing] AS [D]        INNER JOIN        (SELECT            [T].[ID],            MAX(Distance([T].[Coord], [U].[Coord])) AS [w]        FROM             [Query 1] AS [T]            INNER JOIN            [Query 1] AS [U]            ON [T].[ID] = [U].[ID]            AND [T].[Coord] < [U].[Coord]        GROUP BY [T].[ID]        ) AS [V]        ON [D].[ID] = [V].[ID]    )SET [width] = [w];
Manifold User Community Use Agreement Copyright (C) 2007-2021 Manifold Software Limited. All rights reserved.