Subscribe to this thread
Home - General / All posts - Create and save to file images of objects on the map
miqqq4 post(s)
#08-May-24 01:16

My goal is to generate raster images for each object in the shapefile and save them to a file. I know how to do it using the UI, but I have thousands of objects that I have to process. Doing it manually is out of question. Below, I am trying to create an image and then save it using db.export().

The problem is that TileRenderWindow function accepts projected coordinates(?), but GeomBoundsRect gives relative coordinates. Having spent hours looking into this, I am stuck. How do I get correct coordinates. Alternatively, is there a better approach to generate map images of all objects and save them to files?

CREATE TABLE [Map Image Table] (

[mfd_id] INT64,

[X] INT32,

[Y] INT32,

[Tile] TILE,

INDEX [mfd_id_x] BTREE ([mfd_id]),

INDEX [X_Y_Tile_x] RTREE ([X], [Y], [Tile] TILESIZE (128, 128) TILETYPE UINT8X4),

PROPERTY 'FieldCoordSystem.Tile' '{ "Axes": "XYH", "Base": "WGS 84 (EPSG:4326)", "CenterLat": 0, "CenterLon": 0, "Eccentricity": 0.08181919084262149, "LocalOffsetX": -8941500.920347098, "LocalOffsetY": 3176485.71572937, "LocalScaleX": 0.19862648476981273, "LocalScaleY": 0.19862648477113656, "MajorAxis": 6378137, "Name": "WGS 84 \/ Pseudo-Mercator (EPSG:3857)", "System": "Pseudo Mercator", "Unit": "Meter", "UnitScale": 1, "UnitShort": "m" }',

PROPERTY 'FieldTileSize.Tile' '[ 128, 128 ]',

PROPERTY 'FieldTileType.Tile' 'uint8x4'

);

CREATE IMAGE [Map Image] (

PROPERTY 'Table' '[Map Image Table]',

PROPERTY 'FieldTile' 'Tile',

PROPERTY 'FieldX' 'X',

PROPERTY 'FieldY' 'Y',

PROPERTY 'Rect' '[ 0, 0, 1244, 889 ]'

);

INSERT INTO [Map Image Table] ([X], [Y], [Tile])

SELECT [X], [Y], [Tile] FROM CALL TileRenderWindow('Map',

(SELECT GeomBoundsRect([Geom]) FROM [Cats] WHERE [id]=1990),

VectorMakeX2(1244, 889),

VectorMakeX2(128, 128),

96, false);

TABLE CALL TileUpdatePyramids([Map Image]);

Thank you,

Dimitri


7,479 post(s)
#08-May-24 06:27

The problem is that TileRenderWindow function accepts projected coordinates(?),

That's explicitly covered in the documentation on TileRender in the Tile SQL Functions topic. Start by reviewing that. Note the advice to use the Edit Query button in the Edit - Save as Image command to get examples of how to use such functions.

For example, using a satellite image and zooming into the Louvre and then using the Edit Query in the Save as Image command, you can see something like...

CREATE TABLE [Bing Maps Satellite Image Image Table] (

  [mfd_id] INT64,

  [X] INT32,

  [Y] INT32,

  [Tile] TILE,

  INDEX [mfd_id_x] BTREE ([mfd_id]),

  INDEX [X_Y_Tile_x] RTREE ([X][Y][Tile] TILESIZE (128, 128) TILETYPE UINT8X4),

  PROPERTY 'FieldCoordSystem.Tile' '{ "Axes": "XYH", "Base": "WGS 84 (EPSG:4326)", "CenterLat": 0, "CenterLon": 0, 

"Eccentricity": 0.08181919084262149, "LocalOffsetX": 259446.75105703622, "LocalOffsetY": 6251151.822671514, 

"LocalScaleX": 0.8301225112979417, "LocalScaleY": 0.8301225112977758, "MajorAxis": 6378137, "Name"

"WGS 84 \/ Pseudo-Mercator (EPSG:3857)""System""Pseudo Mercator""Unit""Meter""UnitScale": 1, "UnitShort""m" }',

  PROPERTY 'FieldTileSize.Tile' '[ 128, 128 ]',

  PROPERTY 'FieldTileType.Tile' 'uint8x4'

);

CREATE IMAGE [Bing Maps Satellite Image Image] (

  PROPERTY 'Table' '[Bing Maps Satellite Image Image Table]',

  PROPERTY 'FieldTile' 'Tile',

  PROPERTY 'FieldX' 'X',

  PROPERTY 'FieldY' 'Y',

  PROPERTY 'Rect' '[ 0, 0, 1084, 594 ]'

);

INSERT INTO [Bing Maps Satellite Image Image Table] ([X][Y][Tile])

SELECT [X][Y][Tile] FROM CALL TileRenderWindow('Bing Maps Satellite Image',

  VectorMakeX4(67977793.23182209, 88044984.91555186, 67980806.9847445, 88046636.36318646),

  VectorMakeX2(1084, 594),

  VectorMakeX2(128, 128),

  96, false);

TABLE CALL TileUpdatePyramids([Bing Maps Satellite Image Image]);

Note the use of pseudo-mercator coordinates.

GeomBoundsRect (see the documentation) returns an x4 value that is the x,y locations of the diagonally opposite corners of the rect in the coordinate system of the geom.

It's not clear what you intend to do, but I get the impression that you have a map with two layers, a drawing layer (remember, once you import from a shapefile it is a drawing that has no connection to any shapefile) and some raster image layer. For each object in the drawing, you want to find the bounding rectangle and then create a raster image that covers that bounding rectangle using the raster layer. Is that it?

If so, just use the same projection for the raster layer (likely pseudo mercator), the drawing layer and the map. Keep it simple. If the source shapefile was in some other projection so the drawing that was imported is in some other projection, reproject it into the same projection as the map and raster layer. You can then use the same coordinates throughout with no need to convert any using coordinate converter objects, etc.

miqqq4 post(s)
#08-May-24 17:48

It's not clear what you intend to do, but I get the impression that you have a map with two layers, a drawing layer (remember, once you import from a shapefile it is a drawing that has no connection to any shapefile) and some raster image layer. For each object in the drawing, you want to find the bounding rectangle and then create a raster image that covers that bounding rectangle using the raster layer. Is that it?

Yes, this is it.

I read the documentation on TileRender and reprojected the component. Both projections are the same.

For the green rectangle (see the attachment), the coordinates from the Info tab are

C -29343169.662354197 10394759.82587711

C -29343027.679216094 10394759.074205786

C -29343026.187729806 10395043.715820601

C -29343168.171750665 10395044.467518779

E -29343169.662354197 10394759.82587711

I can also I run query on shape file, SELECT GeomBoundsRect([Geom]) FROM [Cats] WHERE [id]=1990, I get the same coordinates

[ -29343169.662354197, 10394759.074205786, -29343026.187729806, 10395044.467518779]

If I use the Edit Query button in the Edit - Save as Image command, the coordinates shown in the coordinates passed to TileRenderWindow are very different:

TileRenderWindow('Map 2',

VectorMakeX4(-8943894.428632382, 3168292.149998029, -8943666.291973386, 3168455.1833499954),

VectorMakeX2(1244, 889),

VectorMakeX2(128, 128), 96, false);

I do not understand where/how do I get coordinates to use with TileRenderWindow to render a specified object in the shapefile.

Attachments:
shape.jpg

Dimitri


7,479 post(s)
#09-May-24 04:48

The Edit Query button on Edit - Save as Image will generate a query that renders the image for whatever is set up in the Save as Image dialog, not limited to a single object, right? So the coordinates of the bounding box for the window are going to be different than the coordinates of the bounding box for some object that is smaller than the window.

What image do you get when you use the coords from your green rectangle to create an image using TileRenderWindow?

I do not understand where/how do I get coordinates to use with TileRenderWindow to render a specified object in the shapefile.

You would iterate through all of the objects in the drawing layer. For each object, 1) get the coordinates of the bounding box for that object, and 2) use those coordinates to make an image. That's best done I think using a small script that calls a snippet of SQL within the script.

If you'd like to learn about the bits and pieces that go into the above, you can do the process semi-manually using the Transform pane.

For example, take the table for your drawing of objects, and use the Transform pane to add a second geom field to each row which is the bounding box for the object in that row. You can use Edit Query on that transform to see the SQL which does that.

You can then extract from each bounding box geom the coords (as you've done) and put them into x4 data type columns, and then extract each individual coord if you want. Using Edit Query for each such step shows you the SQL for it, which teaches the various SQL functions used.

miqqq4 post(s)
#09-May-24 08:14

For each object, 1) get the coordinates of the bounding box for that object, and 2) use those coordinates to make an image.

I have a problem with 2). Despite the map and a shape using the same projection (I reprojected shape file to match the raster map), the coordinates stored in<geom> are not the same coordinates that go into TileRenderWindow. In other words, I cannot take coordinates from <geom> object and pass them to TileRenderWindow. If I do so, then the resulting image will show some other piece of terrain, not where the shape is. It seems to me that I need to find projected coordinates of a shape before passing them to TileRenderWindow. By projected coordinates, I mean coordinates shown in the bottom right corner of Manifold.

Again, I do not believe that reprojection solves this problem. While reprojection changes coordinates stored in <geom> object, those are not the same coordinates that I can pass to TileRenderWindow. I clarified what I am asking on the attached image.

Thank you for you help,

Attachments:
question.png

miqqq4 post(s)
#10-May-24 05:23

I solved the problem by creating a new map using the original system of coordinates of the shapefile. Now, the coordinates stored in the <geom> can be used directly with TileRenderWindow function. While the solution works great, I still do not understand why reprojecting both raster and shapes to Pseudo-Mercator did not work as the map looked perfectly fine. Originally, I used Pseudo-Mercator for both rasters and shapefiles assuming thatManifold would transform them to the same system of coordinates, but for some reason it did not.

Dimitri


7,479 post(s)
#10-May-24 07:11

You don't mention how you reprojected. For example, it might be that you just changed the projection of the map window but did not reproject the drawing. If you open the map window, click on the drawing tab to make it the active layer, and then look at the Info pane that will show you the projection used for the map and also the projection used for that active layer, that is, the drawing.

Manifold User Community Use Agreement Copyright (C) 2007-2021 Manifold Software Limited. All rights reserved.