aboutsummaryrefslogtreecommitdiff
path: root/iosApp/WhirlyGlobeMaplyComponent.xcframework/ios-arm64/WhirlyGlobeMaplyComponent.framework/Headers/MaplyVectorObject.h
blob: e85aeb429b33d9163cce4885e52644c67ce116c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
/*  MaplyVectorObject.h
 *  WhirlyGlobeComponent
 *
 *  Created by Steve Gifford on 8/2/12.
 *  Copyright 2012-2022 mousebird consulting
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <WhirlyGlobeMaplyComponent/MaplyCoordinate.h>
#import <WhirlyGlobeMaplyComponent/MaplyCoordinateSystem.h>

@class MaplyBaseViewController;

/// Data type for the vector.  Multi means it contains multiple types
typedef NS_ENUM(NSInteger, MaplyVectorObjectType) {
	MaplyVectorNoneType,
	MaplyVectorPointType,
    MaplyVectorLinearType,
    MaplyVectorLinear3dType,
	MaplyVectorArealType,
	MaplyVectorMultiType,
};


/** 
    Maply Vector Object represents zero or more vector features.
    
    The Vector Object can hold several vector features of the same or different types.  It's meant to be a fairly opaque structure, often read from GeoJSON or Shapefiles.  It's less opaque than originally planned, however, and sports a number of specific methods.
    
    If you're doing real vector manipulation, it's best to do it somewhere else and then create one of these as needed for display.
    
    Vector Objects can be created directly or read from a MaplyVectorDatabase.  They are typically then displayed on top of a MaplyViewController or WhirlyGlobeViewController as vectors.
    
    Vector Objects vertices are always in geographic, with longitude = x and latitude = y.
  */
@interface MaplyVectorObject : NSObject

/// Turn this off to make this vector invisible to selection.
/// On by default.
@property (nonatomic,assign) bool selectable;

/** 
    Return the attributes for the vector object.
    
    All vectors should have some set of attribution.  If there's more than one vector feature here, we'll return the attributes on the first one.
    
    The attribution is returned as an NSDictionary and, though you can modify it, you probably shouldn't.
  */
@property (nonatomic,readonly) NSMutableDictionary *__nullable attributes;

/** 
    Parse vector data from geoJSON.
    
    Returns one object to represent the whole thing, which might include multiple different vectors.  This version uses the faster JSON parser.
    
    We assume the geoJSON is all in decimal degrees in WGS84.
  */
+ (MaplyVectorObject *__nullable)VectorObjectFromGeoJSON:(NSData *__nonnull)geoJSON;

/** 
    Parse vector data from geoJSON.
    
    Returns one object to represent the whole thing, which might include multiple different vectors.  This version uses slower JSON parser.
    
    We assume the geoJSON is all in decimal degrees in WGS84.
*/
+ (MaplyVectorObject *__nullable)VectorObjectFromGeoJSONApple:(NSData *__nonnull)geoJSON;

/** 
    Parse vector data from geoJSON.
    
    Returns one object to represent the whole thing, which might include multiple different vectors.  This version parses its data from an NSDictionary, which had to be parsed from JSON at some point.  Probably the slower path.
    
    We assume the geoJSON is all in decimal degrees in WGS84.
 */
+ (MaplyVectorObject *__nullable)VectorObjectFromGeoJSONDictionary:(NSDictionary *__nonnull)geoJSON;

// Note: Reader turned off
#if 0
/** 
    Read vector objects from the given cache file.
    
    MaplyVectorObject's can be written and read from a binary file.  We use this for caching data locally on the device.
    
    @param fileName Name of the binary vector file.
    
    @return The vector object(s) read from the file or nil on failure.
  */
+ (MaplyVectorObject *__nullable)VectorObjectFromFile:(NSString *__nonnull)fileName;
#endif

/** 
    Read vector objects from the given shapefile.
    
    This will read all the shapes in the given shapefile into memory and return them as one MaplyVectorObject.
    
    @param fileName The basename of the shape file.  Don't include the extension.
    
    @return The vector object(s) read from the file or nil on failure.
  */
+ (MaplyVectorObject *__nullable)VectorObjectFromShapeFile:(NSString *__nonnull)fileName;

/** 
    Parse vector objects from a JSON assembly.
    
    This version can deal with non-compliant assemblies returned by the experimental OSM server
  */
+ (NSDictionary *__nullable)VectorObjectsFromGeoJSONAssembly:(NSData *__nonnull)geoJSON;

/** 
    Initialize with a single data point and attribution.
 
    This version takes a single coordinate and the attributes to go with it.
 */
- (nonnull instancetype)initWithPoint:(MaplyCoordinate)coord attributes:(NSDictionary *__nullable)attr;

/** 
    Initialize with a single data point and attribution.
    
    This version takes a single coordinate and the attributes to go with it.
  */
- (nonnull instancetype)initWithPointRef:(const MaplyCoordinate *__nonnull)coord attributes:(NSDictionary *__nullable)attr;

/** 
    Initialize with a linear feature.
 
    This version takes an array of coordinates (2 `NSNumber`s per coordinate, in degrees) and the attribution.
    With this it will make a linear feature.
    Prefer the `inDegrees:` overload to reduce ambiguity.
    Returns nil if the coordinate array contains an odd number of values.
 */
- (nullable instancetype)initWithLineString:(const NSArray<NSNumber*> *__nonnull)coords
                                attributes:(NSDictionary *__nullable)attr;

/**
    Initialize with a linear feature.
 
    This version takes an array of coordinate pairs (as NSNumber) and the attribution.  With this it will make a linear feature.
    Returns nil if the coordinate array contains an odd number of values.
 */
- (nullable instancetype)initWithLineString:(const NSArray<NSNumber*> *__nonnull)coords
                                attributes:(NSDictionary *__nullable)attr
                                 inDegrees:(bool)inDegrees;

/** 
    Initialize with a linear feature.
 
    This version takes an array of coordinates, the size of that array and the attribution.  With this it will make a linear feature.
  */
- (nonnull instancetype)initWithLineString:(const MaplyCoordinate *__nonnull)coords
                                 numCoords:(int)numCoords
                                attributes:(NSDictionary *__nullable)attr;

/** 
    Inintialize as an areal feature.
 
    This version takes an array of coordinates, the size of that array and the attribution.
    With this it will make a single area feature with one (exterior) loop.  To add loops, call `addHole:numCoords:`
  */
- (nonnull instancetype)initWithAreal:(const MaplyCoordinate *__nonnull)coords
                            numCoords:(int)numCoords
                           attributes:(NSDictionary *__nullable)attr;

/**
  Inintialize as an areal feature.
 
    This version takes an array of coordinates (2 `NSNumber`s per coordinate, in radians).
    With this it will make a single area feature with one (exterior) loop.  To add loops, call addHole:numCoords:
    Prefer the `inDegrees:` overload to reduce ambiguity.
    Returns nil if the coordinate array contains an odd number of values.
*/
- (nullable instancetype)initWithArealArray:(const NSArray<NSNumber *> *__nonnull)coords
                                 attributes:(NSDictionary *__nullable)attr;

/**
    Inintialize as an areal feature.
 
    This version takes an array of coordinates (2 `NSNumber`s per coordinate, in radians).
    With this it will make a single area feature with one (exterior) loop.  To add loops, call `addHole:numCoords:`
    Returns nil if the coordinate array contains an odd number of values.
*/
- (nullable instancetype)initWithArealArray:(const NSArray<NSNumber *> *__nonnull)coords
                                 attributes:(NSDictionary *__nullable)attr
                                  inDegrees:(bool)inDegrees;

/** 
    Initializes with vectors parsed from geoJSON.
	
    Returns one object to represent the whole thing, which might include multiple different vectors.  This version uses the faster JSON parser.
    
    We assume the geoJSON is all in decimal degrees in WGS84.
 */
- (nullable instancetype)initWithGeoJSON:(NSData *__nonnull)geoJSON;

/** 
    Initializes with vector parsed from geoJSON.
	
    Returns one object to represent the whole thing, which might include multiple different vectors.  This version uses slower JSON parser.
	
    We assume the geoJSON is all in decimal degrees in WGS84.
 */
- (nullable instancetype)initWithGeoJSONApple:(NSData *__nonnull)geoJSON;

/** 
    Initializes with vector parsed from geoJSON.
	
    Returns one object to represent the whole thing, which might include multiple different vectors.  This version parses its data from an NSDictionary, which had to be parsed from JSON at some point.  Probably the slower path.
	
    We assume the geoJSON is all in decimal degrees in WGS84.
 */
- (nullable instancetype)initWithGeoJSONDictionary:(NSDictionary *__nonnull)geoJSON;

// Note: Turned off with reading
#if 0
/** 
    Initializes with vectors read from the given cache file.
	
    MaplyVectorObject's can be written and read from a binary file.  We use this for caching data locally on the device.
	
    @param fileName Name of the binary vector file.
	
    @return The vector object(s) read from the file or nil on failure.
 */
- (nullable instancetype)initWithFile:(NSString *__nonnull)fileName;
#endif

/** 
    Initializes with vectors read from the given shapefile.
	
    This will read all the shapes in the given shapefile into memory and return them as one MaplyVectorObject.
	
    @param fileName The basename of the shape file.  Don't include the extension.
	
    @return The vector object(s) read from the file or nil on failure.
 */
- (nullable instancetype)initWithShapeFile:(NSString *__nonnull)fileName;


// Note: Vector writing turned off
#if 0
/** 
    Write the vector object to the given file on the device.
    
    We support a binary format for caching vector data.  Typically you write these files on the device or in the simulator and then put them in a place you can easily find them when needed.
    
    @param fileName The file to read the vector data from.
    
    @return Returns true on succes, false on failure.
  */
- (bool)writeToFile:(NSString *__nonnull)fileName;
#endif

/** 
    Make a deep copy of the vector object and return it.
    
    This makes a complete copy of the vector object, with all features and nothing shared.
    
    Had to rename this because Apple's private method scanner is dumb.
  */
- (MaplyVectorObject *__nonnull)deepCopy2;

/** 
    Reproject from one coordinate system to another.
    
    This reprojects every single point in the points, linears, and areals (and mesh) from the source coordinate system to the destionation.
    
    Typically, you'll want Plate Carree for display, the destSystem is probably that.
    
    For various reasons (e.g. scale), this will probably not work right for you.
    
    @param srcSystem The source coordinate system.  The data is already in this sytem.
    
    @param destSystem The destination coordinate system.  The data will be in this system on return.
  */
- (void)reprojectFrom:(MaplyCoordinateSystem *__nonnull)srcSystem to:(MaplyCoordinateSystem *__nonnull)destSystem;

/** 
    Dump the feature(s) out as text
    
    This will write each feature out as text for debugging.
  */
- (NSString *__nonnull)log;

/** 
    Add a hole to an existing feature.
    
    This method is expecting to find exactly one areal feature.  If it finds one, it will add the given hole as a loop on the end of the list of loops.
  */
- (void)addHole:(const MaplyCoordinate *__nonnull)coords numCoords:(int)numCoords;

/** 
    Returns the type of the vector feature.
    
    This method returns the type of the vector.  Since vector objects can contain multiple types of vectors at once, this is somewhat complicated.
 
|Type | Description |
|:----|:-----------:|
|MaplyVectorNoneType | There are no features in this object. |
|MaplyVectorPointType | There are only points (and multi-points) in the object. |
|MaplyVectorLinearType | There are only linear features in the object. |
|MaplyVectorLinear3dType | There are only linear features with Z values in the object. |
|MaplyVectorArealType | There are only areal features in the object. |
|MaplyVectorMultiType | There are multiple features of different types in the object. |
  */
- (MaplyVectorObjectType)vectorType;

/** 
    Run a point in polygon test on all the areal features within the object.
    
    We'll run a point in polygon test on all the areal features within the vector object.  If the point is within one of them, we return true, otherwise false.
  */
- (bool)pointInAreal:(MaplyCoordinate)coord;

/**
    Test if any linear feature is within distance of coord
 */
- (bool)pointNearLinear:(MaplyCoordinate)coord distance:(float)maxDistance inViewController:(MaplyBaseViewController *__nonnull)vc;

/** 
    Calculate the center of the entire set of vectors in this object.
  */
- (MaplyCoordinate)center;

/** 
    Copy the vectors in the given vector object into this one.
  */
- (void)mergeVectorsFrom:(MaplyVectorObject *__nonnull)otherVec;

/** 
    For a linear feature, calculate the mid oint and rotation at that point.
    
    The vector object contains a number of half baked geometric queries, this being one of them.
    
    This finds the middle (as measured by distance) of a linear feature and then calculations an angle corresponding to the line segment that middle sits in.
    
    Why?  Think label road placement.
  */
- (bool)linearMiddle:(MaplyCoordinate *__nonnull)middle rot:(double *__nonnull)rot;

- (bool)linearMiddle:(MaplyCoordinate *__nullable)middle rot:(double *__nullable)rot displayCoordSys:(MaplyCoordinateSystem *__nonnull)coordSys;

/** 
    For a linear feature, calculate the mid point.
 
    This is a convenience method to be called without pointers (Swift)
 
    If you need both the mid point and the rotation, this method is less efficient than the method with pointers.
 
    @return kMaplyNullCoordinate in case of error

 */
- (MaplyCoordinate)linearMiddle:(MaplyCoordinateSystem *__nonnull)coordSys;

/** 
    For a linear feature, calculate the mid point and returns the rotation at that point.
 
    This is a convenience method to be called without pointers (Swift)
 
    If you need both the mid point and the rotation, this method is less efficient than the method with pointers.
 
    @return DBL_MIN in case of error
 */
- (double)linearMiddleRotation:(MaplyCoordinateSystem *__nonnull)coordSys;

/** 
    return the middle coordinate in a line feature
    
    @return kMaplyNullCoordinate in case of error
 */
- (MaplyCoordinate)middleCoordinate;

/** 
    return the middle coordinate in a line feature.
 */
- (bool)middleCoordinate:(MaplyCoordinate *__nonnull)middle;

/** 
    Calculate the center and extents of the largest loop in an areal feature.
    
    The vector object contains a number of half baked geometric queries, this being one of them.
    
    If this vector contains at least one areal feature, we'll determine which loop is the largest and return the center of that loop, as well as its bounding box.
    
    Why?  Think label placement on an areal feature.
    
    @return Returns false if there was no loop (i.e. probably isn't an areal)
  */
- (bool)largestLoopCenter:(MaplyCoordinate *__nullable)center mbrLL:(MaplyCoordinate *__nullable)ll mbrUR:(MaplyCoordinate *__nullable)ur;

/** 
    Calculate the centroid of the largest loop in the areal feature.
 
    The centroid is a better center for label placement than the middle of the largest loop as calculated by largestLoopCenter:mbrLL:mbrUR:
 
    @return Returns the centroid structure. If there was no loop (i.e. probably isn't an areal), the result will be kMaplyNullCoordinate
 */
- (MaplyCoordinate)centroid;

/** 
    Calculate the centroid of the largest loop in the areal feature.
    
    The centroid is a better center for label placement than the middle of the largest loop as calculated by largestLoopCenter:mbrLL:mbrUR:
    
    @return Returns false if there was no loop (probably wasn't an areal).
  */
- (bool)centroid:(MaplyCoordinate *__nonnull)centroid;

/** 
    Calculate the bounding box of all the features in this vector object.
 
    @return kMaplyNullBoundingBox in case of error
 */
- (MaplyBoundingBox)boundingBox;

/** 
    Calculate the bounding box of all the features in this vector object.
  */
- (bool)boundingBoxLL:(MaplyCoordinate *__nonnull)ll ur:(MaplyCoordinate *__nonnull)ur;

/** 
    Calculate the area of the outer loops.
    
    This returns the area of the outer loops of any areal features in the VectorObject.
  */
- (double)areaOfOuterLoops;

/** 
    Convert any linear features into areal features.
    
    Convert linear features to areal features by closing each one individually.
  */
- (MaplyVectorObject * _Nonnull )linearsToAreals;

/**
    Convert any areal features into outlines.
  */
- (MaplyVectorObject * __nonnull)arealsToLinears;

/**
    Reverse the direction of areal loops in-place
 */
- (void)reverseAreals;

/**
    Return a copy with the areal loops reversed
 */
- (MaplyVectorObject * __nonnull)reversedAreals;

/**
    Filter out edges created from clipping areal features on the server.
 
    In some very specific cases (OSM water) we get polygons that are obviously clipped
    along internal boundaries.  We can clear this up with some very, very specific logic.
 
    Input must be closed areals and output is linears.
  */
- (MaplyVectorObject *__nonnull)filterClippedEdges;

/** 
    Convert a feature to an NSArray of NSArrays of CLLocation points.
    
    This is intended for areal features.  It will convert those coordinates to CLLocation values and return them.  Obviously this is intended for things that need CLLocation values.
    
    @return Returns an NSArray of NSArray's which then contain CLLocation points.
  */
- (NSArray *__nullable)asCLLocationArrays;

/** 
    Return the data as an NSArray of NSNumbers.
    
    If this is a linear, we'll return the points as an NSArray of NSNumbers.
  */
- (NSArray *__nullable)asNumbers;

/** 
    Split up this feature into individual features and return an array of them.
    
    A vector object can represent multiple features with no real rhyme or reason to it.  This method will make one vector object per feature, allowing you to operate on those individually.
    
    @return An NSArray of MaplyVectorObject.
  */
- (NSArray<MaplyVectorObject *> *__nonnull)splitVectors;

/** 
    Subdivide the edges in this feature to a given tolerance.
    
    This will break up long edges in a vector until they lie flat on a globe to a given epsilon.  The epislon is in display coordinates (radius = 1.0). This routine breaks this up along geographic boundaries.
  */
- (void)subdivideToGlobe:(float)epsilon;

/** 
    Subdivide the edges in this feature to a given tolerance, using great circle math.
    
    This will break up long edges in a vector until they lie flat on a globe to a given epsilon using a great circle route.  The epsilon is in display coordinates (radius = 1.0).
  */
- (void)subdivideToGlobeGreatCircle:(float)epsilon;

/** 
    Subdivide the edges in this feature to a given tolerance, using great circle math.
 
    This version samples a great circle to display on a flat map.
 */
- (void)subdivideToFlatGreatCircle:(float)epsilon;


/**
    Subdivide the edges in this feature to a given tolerance, using ellipsoidal great circle math.
    
    This will break up long edges in a vector until they lie flat on a globe to a given epsilon using a great circle route.  The epsilon is in display coordinates (radius = 1.0).
  */
- (void)subdivideToGlobeGreatCirclePrecise:(float)epsilon;

/**
    Subdivide the edges in this feature to a given tolerance, using ellipsoidal  great circle math.
 
    This version samples a great circle to display on a flat map.
 */
- (void)subdivideToFlatGreatCirclePrecise:(float)epsilon;

/** 
    Tesselate the areal geometry in this vector object and return triangles.
    
    This will attempt to tesselate the areals (with holes) and turn them into triangles.  No attribution will be assigned to the new triangles, so be aware.  The tesselator is the GLU based one and does a decent job.  Odds are if there's something wrong it's in the input data.
  */
- (MaplyVectorObject *__nonnull)tesselate;

/** 
    Clip the given (presumably areal) feature(s) to a grid in radians of the given size.
    
    This will run through the loops in the input vectors and clip them against a grid.  The grid size is given in radians.
    
    @return New areal features broken up along the grid.
  */
- (MaplyVectorObject *__nullable)clipToGrid:(CGSize)gridSize;

/**
    
    Clip the given (probably areal) features to the given bounding box.
    
    This will run through the loops of the areal features and clip them against a bounding box.
    
    The bounding box should be in the same coordinate system as the grid, probably radians.
    
    @return The new areal features will be clipped along the bounding box.
  */
- (MaplyVectorObject *__nullable)clipToMbr:(MaplyCoordinate)ll upperRight:(MaplyCoordinate)ur;

@end

typedef MaplyVectorObject WGVectorObject;