|
OK finally I have things working as they should. Apologies for the delay. There are now two versions. The first version draws ordinary circles around each selected object in [Drawing], in its native coordinate system, using the radius and the number of coordinates supplied by the user. As we have discussed (and as discussed in the manual), where the drawing uses a projection that shows significant distortion at the current location (as is often the case with Google/Bing pseudo-projections, and many compromise projections), the "circles" that are drawn will look circular, but not describe accurate circles on the Earth. To draw accurate circles, we can use Manifold's built-in Geographic Circle function, to draw one circle at a time, or use the second query below. This follows the same method as Geographic Circle, i.e. it draws circles in an Azimuthal Equidistant projection centred on the chosen location, or here, centred on each selected object. Most of the interesting stuff is in the second query, specifically in making a custom Azimuthal Equidistant projection centred on each object. We currently have to go via the WKT for a default projection, centred at (0, 0), and use regular expressions to splice in custom parameters. (So this is one thing that is miles easier via the object model than in SQL.) The method can easily be adapted for other projections. (The RegExp code is commented at the bottom.) For both queries, if you don't enter a radius or a number of coordinates, then defaults of 10 units and 32 coordinates are used. Both queries draw areas. Change one function name to give lines. The first query is much like the earlier versions above, except that it's fixed to draw a separate circle for each selected object (normally much more useful). The second query is much like Geographic Circle in the GUI, except that it draws any number of circles at a time. Query 1 (Draw projected circles): -- Draw a circle about each selected object in [Drawing] -- in projected (native) space PARAMETERS [Radius (10)] DOUBLE, [Coordinates (32)] SINGLE; INSERT INTO [Drawing] ([Geom (I)]) SELECT ConvertToArea(AllCoords([arc point])) FROM (SELECT [ID], AssignCoordSys( NewPoint( CentroidX([point]) + [r] * Sin([arc]), CentroidY([point]) + [r] * Cos([arc]) ), CoordSys("Drawing" AS COMPONENT) ) AS [arc point] FROM (SELECT [ID], Centroid([Geom (I)]) AS [point] -- NB point, for any object type FROM [Drawing] WHERE [Selection (I)] ) CROSS JOIN (SELECT [r], 2 * [pi] / [m] * [n] AS [arc] -- cursor angle in radians FROM (VALUES ( Coalesce([Radius (10)], 10), -- default radius 10 units Coalesce([Coordinates (32)], 32), -- default 32 coordinates 4 * Atn(1) -- pi ) NAMES ([r], [m], [pi]) ) LEFT JOIN (SELECT [1e3] * 1e3 + [100] * 100 + [ten] * 10 + [one] AS [n] FROM (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9) NAMES ([1e3])) CROSS JOIN (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9) NAMES ([100])) CROSS JOIN (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9) NAMES ([ten])) CROSS JOIN (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9) NAMES ([one])) ) ON [n] < [m] ) ) GROUP BY [ID]; Query 2 (Draw geographic circles): -- Draw a circle about each selected object in [Drawing] -- in geographic space -- (using a custom Azimuthal Equidistant projection -- centred on each object) PARAMETERS [Radius (10)] DOUBLE, [Coordinates (32)] SINGLE; INSERT INTO [Drawing] ([Geom (I)]) SELECT ConvertToArea(AllCoords([arc point])) FROM (SELECT [ID], Project( AssignCoordSys( NewPoint( CentroidX([point AE]) + [r] * Sin([arc]), CentroidY([point AE]) + [r] * Cos([arc]) ), [AE local] ), CoordSys("Drawing" AS COMPONENT) ) AS [arc point] FROM (SELECT [ID], [AE local], Project([point native], [AE local]) AS [point AE] FROM (SELECT [ID], [point native], WktToCoordSys( RegExp( RegExp([AE origin WKT], [findCX], CAST(CentroidX([point geographic]) AS TEXT) ), [findCY], CAST(CentroidY([point geographic]) AS TEXT) ) ) AS [AE local] -- custom Azimuthal Equidistant projection, centred at this point FROM (SELECT [ID], Centroid([Geom (I)]) AS [point native], -- NB point, for any object type Project(Centroid([Geom (I)]), CoordSys("Latitude / Longitude")) AS [point geographic] FROM [Drawing] WHERE [Selection (I)] ) CROSS JOIN (VALUES ( -- default Azimuthal Equidistant projection, centred at (0, 0) CoordSysToWkt(COORDSYS("Azimuthal Equidistant")), -- search strings to recentre default Azimuthal Equidistant projection (note 1) "(?<=\[\x22Central_Meridian\x22,)\d+\.?\d*(?=\])", "(?<=\[\x22Latitude_Of_Origin\x22,)\d+\.?\d*(?=\])" ) NAMES ([AE origin WKT], [findCX], [findCY]) ) ) ) CROSS JOIN (SELECT [r], 2 * [pi] / [m] * [n] AS [arc] -- cursor angle in radians FROM (VALUES ( Coalesce([Radius (10)], 10), -- default radius 10 units Coalesce([Coordinates (32)], 32), -- default 32 coordinates 4 * Atn(1) -- pi ) NAMES ([r], [m], [pi]) ) LEFT JOIN (SELECT [1e3] * 1e3 + [100] * 100 + [ten] * 10 + [one] AS [n] FROM (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9) NAMES ([1e3])) CROSS JOIN (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9) NAMES ([100])) CROSS JOIN (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9) NAMES ([ten])) CROSS JOIN (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9) NAMES ([one])) ) ON [n] < [m] ) ) GROUP BY [ID]; -- Notes -- 1 -- RegExp search strings -- "(?<=\[\x22Central_Meridian\x22,)\d+\.?\d*(?=\])" -- "(?<=\[\x22Latitude_Of_Origin\x22,)\d+\.?\d*(?=\])" -- positive look-behind (preceding text): '["Central_Meridian",' or '["Latitude_Of_Origin",' -- matched text: one or more digits, optional decimal point, zero or more digits -- positive look-ahead (following text): ']' Attachments: Draw geographic circles.txt Draw projected circles.txt
|