@@ -38,9 +38,9 @@ public static double[] GetGeometriesBoundingBox(NpgsqlConnection conn, string ge
3838 return result ;
3939 }
4040
41- public static List < GeometryRecord > GetGeometrySubset ( NpgsqlConnection conn , string geometry_table , string geometry_column , double [ ] bbox , int source_epsg , int target_srs , string shaderColumn = "" , string attributesColumns = "" , string query = "" , string radiusColumn = "" , bool keepProjection = false )
41+ public static List < GeometryRecord > GetGeometrySubset ( NpgsqlConnection conn , string geometry_table , string geometry_column , double [ ] bbox , int source_epsg , int target_srs , string shaderColumn = "" , string attributesColumns = "" , string query = "" , string radiusColumn = "" , bool keepProjection = false , string idColumn = "" , bool includeTextures = false )
4242 {
43- var sqlselect = GetSqlSelect ( geometry_column , shaderColumn , attributesColumns , radiusColumn , target_srs ) ;
43+ var sqlselect = GetSqlSelect ( geometry_column , shaderColumn , attributesColumns , radiusColumn , target_srs , idColumn ) ;
4444 var sqlFrom = "FROM " + geometry_table ;
4545
4646 // todo: fix unit test when there is no z
@@ -49,7 +49,10 @@ public static List<GeometryRecord> GetGeometrySubset(NpgsqlConnection conn, stri
4949 var sqlWhere = GetWhere ( geometry_column , points . fromPoint , points . toPoint , query , source_epsg , keepProjection ) ;
5050 var sql = sqlselect + sqlFrom + " where " + sqlWhere ;
5151
52- var geometries = GetGeometries ( conn , shaderColumn , attributesColumns , sql , radiusColumn ) ;
52+ var geometries = GetGeometries ( conn , shaderColumn , attributesColumns , sql , radiusColumn , idColumn ) ;
53+ if ( includeTextures ) {
54+ EnrichWithTextures ( conn , geometries ) ;
55+ }
5356 return geometries ;
5457 }
5558
@@ -85,10 +88,13 @@ public static string GetWhere(string geometry_column, Point from, Point to, stri
8588 return where ;
8689 }
8790
88- public static string GetSqlSelect ( string geometry_column , string shaderColumn , string attributesColumns , string radiusColumn , int target_srs )
91+ public static string GetSqlSelect ( string geometry_column , string shaderColumn , string attributesColumns , string radiusColumn , int target_srs , string idColumn = "" )
8992 {
9093 var g = GetGeometryColumn ( geometry_column , target_srs ) ;
9194 var sqlselect = $ "SELECT ST_AsBinary({ g } )";
95+ if ( idColumn != String . Empty ) {
96+ sqlselect = $ "{ sqlselect } , { idColumn } ";
97+ }
9298 if ( shaderColumn != String . Empty ) {
9399 sqlselect = $ "{ sqlselect } , { shaderColumn } ";
94100 }
@@ -107,7 +113,7 @@ public static string GetGeometryColumn(string geometry_column, int target_srs)
107113 return $ "st_transform({ geometry_column } , { target_srs } )";
108114 }
109115
110- public static List < GeometryRecord > GetGeometries ( NpgsqlConnection conn , string shaderColumn , string attributesColumns , string sql , string radiusColumn )
116+ public static List < GeometryRecord > GetGeometries ( NpgsqlConnection conn , string shaderColumn , string attributesColumns , string sql , string radiusColumn , string idColumn = "" )
111117 {
112118 var geometries = new List < GeometryRecord > ( ) ;
113119 conn . Open ( ) ;
@@ -116,11 +122,18 @@ public static List<GeometryRecord> GetGeometries(NpgsqlConnection conn, string s
116122 var attributesColumnIds = new Dictionary < string , int > ( ) ;
117123 var shadersColumnId = int . MinValue ;
118124 var radiusColumnId = int . MinValue ;
125+ var idColumnId = int . MinValue ;
119126
120127 if ( attributesColumns != String . Empty ) {
121128 var attributesColumnsList = attributesColumns . Split ( ',' ) . ToList ( ) ;
122129 attributesColumnIds = FindFields ( reader , attributesColumnsList ) ;
123130 }
131+ if ( idColumn != String . Empty ) {
132+ var fld = FindField ( reader , idColumn ) ;
133+ if ( fld . HasValue ) {
134+ idColumnId = fld . Value ;
135+ }
136+ }
124137 if ( shaderColumn != String . Empty ) {
125138 var fld = FindField ( reader , shaderColumn ) ;
126139 if ( fld . HasValue ) {
@@ -140,6 +153,10 @@ public static List<GeometryRecord> GetGeometries(NpgsqlConnection conn, string s
140153
141154 var geom = Geometry . Deserialize < WkbSerializer > ( stream ) ;
142155 var geometryRecord = new GeometryRecord ( batchId ) { Geometry = geom } ;
156+ if ( idColumn != string . Empty && idColumnId >= 0 ) {
157+ var id = reader . GetFieldValue < object > ( idColumnId ) ;
158+ geometryRecord . SourceId = Convert . ToInt64 ( id ) ;
159+ }
143160
144161 if ( shaderColumn != string . Empty ) {
145162 var json = GetJson ( reader , shadersColumnId ) ;
@@ -164,6 +181,82 @@ public static List<GeometryRecord> GetGeometries(NpgsqlConnection conn, string s
164181 return geometries ;
165182 }
166183
184+ private static void EnrichWithTextures ( NpgsqlConnection conn , List < GeometryRecord > geometries )
185+ {
186+ var sourceIds = geometries
187+ . Where ( g => g . SourceId . HasValue )
188+ . Select ( g => g . SourceId ! . Value )
189+ . Distinct ( )
190+ . ToArray ( ) ;
191+
192+ if ( sourceIds . Length == 0 ) {
193+ return ;
194+ }
195+
196+ var geometriesById = geometries
197+ . Where ( g => g . SourceId . HasValue )
198+ . GroupBy ( g => g . SourceId ! . Value )
199+ . ToDictionary ( g => g . Key , g => g . First ( ) ) ;
200+
201+ const string sql = @"
202+ SELECT g.id,
203+ g.geometry_properties::text AS geometry_properties,
204+ sdm.texture_mapping::text AS texture_mapping,
205+ ti.mime_type,
206+ ti.image_data
207+ FROM citydb.geometry_data g
208+ JOIN citydb.surface_data_mapping sdm
209+ ON sdm.geometry_data_id = g.id
210+ JOIN citydb.surface_data sd
211+ ON sd.id = sdm.surface_data_id
212+ JOIN citydb.tex_image ti
213+ ON ti.id = sd.tex_image_id
214+ WHERE g.id = ANY(@ids)
215+ AND sdm.texture_mapping IS NOT NULL
216+ AND ti.image_data IS NOT NULL
217+ ORDER BY g.id, sdm.surface_data_id" ;
218+
219+ conn . Open ( ) ;
220+ var cmd = new NpgsqlCommand ( sql , conn ) ;
221+ cmd . Parameters . AddWithValue ( "ids" , sourceIds ) ;
222+ var reader = cmd . ExecuteReader ( ) ;
223+
224+ while ( reader . Read ( ) ) {
225+ var sourceId = Convert . ToInt64 ( reader . GetFieldValue < object > ( 0 ) ) ;
226+ if ( ! geometriesById . TryGetValue ( sourceId , out var geometryRecord ) ) {
227+ continue ;
228+ }
229+
230+ if ( string . IsNullOrWhiteSpace ( geometryRecord . GeometryProperties ) ) {
231+ geometryRecord . GeometryProperties = reader . IsDBNull ( 1 ) ? String . Empty : reader . GetString ( 1 ) ;
232+ }
233+
234+ var textureMapping = reader . IsDBNull ( 2 ) ? String . Empty : reader . GetString ( 2 ) ;
235+ var textureMimeType = reader . IsDBNull ( 3 ) ? String . Empty : reader . GetString ( 3 ) ;
236+ var textureImageData = reader . GetFieldValue < byte [ ] > ( 4 ) ;
237+
238+ var texture = new GeometryTexture ( ) {
239+ TextureMapping = textureMapping ,
240+ TextureMimeType = textureMimeType ,
241+ TextureImageData = textureImageData
242+ } ;
243+
244+ if ( texture . IsValid ( ) ) {
245+ geometryRecord . Textures . Add ( texture ) ;
246+ }
247+
248+ // keep legacy fields for backward compatibility with older call paths
249+ if ( string . IsNullOrWhiteSpace ( geometryRecord . TextureMapping ) && geometryRecord . TextureImageData . Length == 0 ) {
250+ geometryRecord . TextureMapping = textureMapping ;
251+ geometryRecord . TextureMimeType = textureMimeType ;
252+ geometryRecord . TextureImageData = textureImageData ;
253+ }
254+ }
255+
256+ reader . Close ( ) ;
257+ conn . Close ( ) ;
258+ }
259+
167260 private static int ? FindField ( NpgsqlDataReader reader , string fieldName )
168261 {
169262 var schema = reader . GetSchemaTable ( ) ;
@@ -221,4 +314,4 @@ private static (Point fromPoint, Point toPoint) GetPoints(double[] bbox)
221314 return ( fromPoint , toPoint ) ;
222315 }
223316
224- }
317+ }
0 commit comments