MaplyVectorObject

Objective-C

@interface MaplyVectorObject : NSObject

Swift

class MaplyVectorObject : NSObject

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.

  • Turn this off to make this vector invisible to selection. On by default.

    Declaration

    Objective-C

    @property (nonatomic) _Bool selectable;

    Swift

    var selectable: Bool { get set }
  • 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.

    Declaration

    Objective-C

    @property (nonatomic, readonly) NSMutableDictionary *_Nullable attributes;

    Swift

    var attributes: NSMutableDictionary? { get }
  • 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.

    Declaration

    Objective-C

    + (MaplyVectorObject *_Nullable)VectorObjectFromGeoJSON:
        (NSData *_Nonnull)geoJSON;

    Swift

    /*not inherited*/ init?(fromGeoJSON geoJSON: Data)
  • 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.

    Declaration

    Objective-C

    + (MaplyVectorObject *_Nullable)VectorObjectFromGeoJSONApple:
        (NSData *_Nonnull)geoJSON;

    Swift

    /*not inherited*/ init?(fromGeoJSONApple geoJSON: Data)
  • 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.

    Declaration

    Objective-C

    + (MaplyVectorObject *_Nullable)VectorObjectFromGeoJSONDictionary:
        (NSDictionary *_Nonnull)geoJSON;

    Swift

    /*not inherited*/ init?(fromGeoJSONDictionary geoJSON: [AnyHashable : Any])
  • 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.

    Declaration

    Objective-C

    + (MaplyVectorObject *_Nullable)VectorObjectFromShapeFile:
        (NSString *_Nonnull)fileName;

    Swift

    /*not inherited*/ init?(fromShapeFile fileName: String)

    Parameters

    fileName

    The basename of the shape file. Don’t include the extension.

    Return Value

    The vector object(s) read from the file or nil on failure.

  • Parse vector objects from a JSON assembly.

    This version can deal with non-compliant assemblies returned by the experimental OSM server

    Declaration

    Objective-C

    + (NSDictionary *_Nullable)VectorObjectsFromGeoJSONAssembly:
        (NSData *_Nonnull)geoJSON;

    Swift

    class func vectorObjects(fromGeoJSONAssembly geoJSON: Data) -> [AnyHashable : Any]?
  • Initialize with a single data point and attribution.

    This version takes a single coordinate and the attributes to go with it.

    Declaration

    Objective-C

    - (nonnull instancetype)initWithPoint:(MaplyCoordinate)coord
                               attributes:(NSDictionary *_Nullable)attr;

    Swift

    init(point coord: MaplyCoordinate, attributes attr: [AnyHashable : Any]? = nil)
  • Initialize with a single data point and attribution.

    This version takes a single coordinate and the attributes to go with it.

    Declaration

    Objective-C

    - (nonnull instancetype)initWithPointRef:(MaplyCoordinate *_Nonnull)coord
                                  attributes:(NSDictionary *_Nullable)attr;

    Swift

    init(pointRef coord: UnsafeMutablePointer<MaplyCoordinate>, attributes attr: [AnyHashable : Any]? = nil)
  • 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.

    Declaration

    Objective-C

    - (nonnull instancetype)initWithLineString:(NSArray *_Nonnull)coords
                                    attributes:(NSDictionary *_Nullable)attr;

    Swift

    init(lineString coords: [Any], attributes attr: [AnyHashable : Any]? = nil)
  • 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.

    Declaration

    Objective-C

    - (nonnull instancetype)initWithLineString:(MaplyCoordinate *_Nonnull)coords
                                     numCoords:(int)numCoords
                                    attributes:(NSDictionary *_Nullable)attr;

    Swift

    init(lineString coords: UnsafeMutablePointer<MaplyCoordinate>, numCoords: Int32, attributes attr: [AnyHashable : Any]? = nil)
  • 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:

    Declaration

    Objective-C

    - (nonnull instancetype)initWithAreal:(MaplyCoordinate *_Nonnull)coords
                                numCoords:(int)numCoords
                               attributes:(NSDictionary *_Nullable)attr;

    Swift

    init(areal coords: UnsafeMutablePointer<MaplyCoordinate>, numCoords: Int32, attributes attr: [AnyHashable : Any]? = nil)
  • Inintialize as an areal feature.

    This version takes an array of coordinates (2 numbers per coordinate). With this it will make a single area feature with one (exterior) loop. To add loops, call addHole:numCoords:

    Declaration

    Objective-C

    - (nonnull instancetype)initWithArealArray:(NSArray<NSNumber *> *_Nonnull)coords
                                    attributes:(NSDictionary *_Nullable)attr;

    Swift

    init(arealArray coords: [NSNumber], attributes attr: [AnyHashable : Any]? = nil)
  • 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.

    Declaration

    Objective-C

    - (nullable instancetype)initWithGeoJSON:(NSData *_Nonnull)geoJSON;

    Swift

    init?(geoJSON: Data)
  • 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.

    Declaration

    Objective-C

    - (nullable instancetype)initWithGeoJSONApple:(NSData *_Nonnull)geoJSON;

    Swift

    init?(geoJSONApple geoJSON: Data)
  • 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.

    Declaration

    Objective-C

    - (nullable instancetype)initWithGeoJSONDictionary:
        (NSDictionary *_Nonnull)geoJSON;

    Swift

    init?(geoJSONDictionary geoJSON: [AnyHashable : Any])
  • 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.

    Declaration

    Objective-C

    - (nullable instancetype)initWithShapeFile:(NSString *_Nonnull)fileName;

    Swift

    init?(shapeFile fileName: String)

    Parameters

    fileName

    The basename of the shape file. Don’t include the extension.

    Return Value

    The vector object(s) read from the file or nil on failure.

  • 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.

    Declaration

    Objective-C

    - (MaplyVectorObject *_Nonnull)deepCopy2;

    Swift

    func deepCopy2() -> MaplyVectorObject
  • 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.

    Declaration

    Objective-C

    - (void)reprojectFrom:(MaplyCoordinateSystem *_Nonnull)srcSystem
                       to:(MaplyCoordinateSystem *_Nonnull)destSystem;

    Swift

    func reproject(from srcSystem: MaplyCoordinateSystem, to destSystem: MaplyCoordinateSystem)

    Parameters

    srcSystem

    The source coordinate system. The data is already in this sytem.

    destSystem

    The destination coordinate system. The data will be in this system on return.

  • Dump the feature(s) out as text

    This will write each feature out as text for debugging.

    Declaration

    Objective-C

    - (NSString *_Nonnull)log;

    Swift

    func log() -> String
  • 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.

    Declaration

    Objective-C

    - (void)addHole:(MaplyCoordinate *_Nonnull)coords numCoords:(int)numCoords;

    Swift

    func addHole(_ coords: UnsafeMutablePointer<MaplyCoordinate>, numCoords: Int32)
  • 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.

    Declaration

    Objective-C

    - (MaplyVectorObjectType)vectorType;

    Swift

    func vectorType() -> MaplyVectorObjectType
  • 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.

    Declaration

    Objective-C

    - (_Bool)pointInAreal:(MaplyCoordinate)coord;

    Swift

    func point(inAreal coord: MaplyCoordinate) -> Bool
  • Test if any linear feature is within distance of coord

    Declaration

    Objective-C

    - (_Bool)pointNearLinear:(MaplyCoordinate)coord
                    distance:(float)maxDistance
            inViewController:(MaplyBaseViewController *_Nonnull)vc;

    Swift

    func pointNearLinear(_ coord: MaplyCoordinate, distance maxDistance: Float, in vc: MaplyBaseViewController) -> Bool
  • Calculate the center of the entire set of vectors in this object.

    Declaration

    Objective-C

    - (MaplyCoordinate)center;

    Swift

    func center() -> MaplyCoordinate
  • Copy the vectors in the given vector object into this one.

    Declaration

    Objective-C

    - (void)mergeVectorsFrom:(MaplyVectorObject *_Nonnull)otherVec;

    Swift

    func mergeVectors(from otherVec: MaplyVectorObject)
  • 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.

    Declaration

    Objective-C

    - (_Bool)linearMiddle:(MaplyCoordinate *_Nonnull)middle
                      rot:(double *_Nonnull)rot;

    Swift

    func linearMiddle(_ middle: UnsafeMutablePointer<MaplyCoordinate>, rot: UnsafeMutablePointer<Double>) -> Bool
  • Undocumented

    Declaration

    Objective-C

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

    Swift

    func linearMiddle(_ middle: UnsafeMutablePointer<MaplyCoordinate>?, rot: UnsafeMutablePointer<Double>?, displayCoordSys coordSys: MaplyCoordinateSystem) -> Bool
  • 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.

    Declaration

    Objective-C

    - (MaplyCoordinate)linearMiddle:(MaplyCoordinateSystem *_Nonnull)coordSys;

    Swift

    func linearMiddle(_ coordSys: MaplyCoordinateSystem) -> MaplyCoordinate

    Return Value

    kMaplyNullCoordinate in case of error

  • 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.

    Declaration

    Objective-C

    - (double)linearMiddleRotation:(MaplyCoordinateSystem *_Nonnull)coordSys;

    Swift

    func linearMiddleRotation(_ coordSys: MaplyCoordinateSystem) -> Double

    Return Value

    DBL_MIN in case of error

  • return the middle coordinate in a line feature

    Declaration

    Objective-C

    - (MaplyCoordinate)middleCoordinate;

    Swift

    func middleCoordinate() -> MaplyCoordinate

    Return Value

    kMaplyNullCoordinate in case of error

  • return the middle coordinate in a line feature.

    Declaration

    Objective-C

    - (_Bool)middleCoordinate:(MaplyCoordinate *_Nonnull)middle;

    Swift

    func middleCoordinate(_ middle: UnsafeMutablePointer<MaplyCoordinate>) -> Bool
  • 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.

    Declaration

    Objective-C

    - (_Bool)largestLoopCenter:(MaplyCoordinate *_Nullable)center
                         mbrLL:(MaplyCoordinate *_Nullable)ll
                         mbrUR:(MaplyCoordinate *_Nullable)ur;

    Swift

    func largestLoopCenter(_ center: UnsafeMutablePointer<MaplyCoordinate>?, mbrLL ll: UnsafeMutablePointer<MaplyCoordinate>?, mbrUR ur: UnsafeMutablePointer<MaplyCoordinate>?) -> Bool

    Return Value

    Returns false if there was no loop (i.e. probably isn’t an areal)

  • 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:

    Declaration

    Objective-C

    - (MaplyCoordinate)centroid;

    Swift

    func centroid() -> MaplyCoordinate

    Return Value

    Returns the centroid structure. If there was no loop (i.e. probably isn’t an areal), the result will be kMaplyNullCoordinate

  • 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:

    Declaration

    Objective-C

    - (_Bool)centroid:(MaplyCoordinate *_Nonnull)centroid;

    Swift

    func centroid(_ centroid: UnsafeMutablePointer<MaplyCoordinate>) -> Bool

    Return Value

    Returns false if there was no loop (probably wasn’t an areal).

  • Calculate the bounding box of all the features in this vector object.

    Declaration

    Objective-C

    - (MaplyBoundingBox)boundingBox;

    Swift

    func boundingBox() -> MaplyBoundingBox

    Return Value

    kMaplyNullBoundingBox in case of error

  • Calculate the bounding box of all the features in this vector object.

    Declaration

    Objective-C

    - (_Bool)boundingBoxLL:(MaplyCoordinate *_Nonnull)ll
                        ur:(MaplyCoordinate *_Nonnull)ur;

    Swift

    func boundingBoxLL(_ ll: UnsafeMutablePointer<MaplyCoordinate>, ur: UnsafeMutablePointer<MaplyCoordinate>) -> Bool
  • Calculate the area of the outer loops.

    This returns the area of the outer loops of any areal features in the VectorObject.

    Declaration

    Objective-C

    - (double)areaOfOuterLoops;

    Swift

    func areaOfOuterLoops() -> Double
  • Convert any linear features into areal features.

    Convert linear features to areal features by closing each one individually.

    Declaration

    Objective-C

    - (MaplyVectorObject *_Nonnull)linearsToAreals;

    Swift

    func linearsToAreals() -> MaplyVectorObject
  • Convert any areal features into outlines.

    Declaration

    Objective-C

    - (MaplyVectorObject *_Nonnull)arealsToLinears;

    Swift

    func arealsToLinears() -> MaplyVectorObject
  • 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.

    Declaration

    Objective-C

    - (MaplyVectorObject *_Nonnull)filterClippedEdges;

    Swift

    func filterClippedEdges() -> MaplyVectorObject
  • 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.

    Declaration

    Objective-C

    - (NSArray *_Nullable)asCLLocationArrays;

    Swift

    func asCLLocationArrays() -> [Any]?

    Return Value

    Returns an NSArray of NSArray’s which then contain CLLocation points.

  • Return the data as an NSArray of NSNumbers.

    If this is a linear, we’ll return the points as an NSArray of NSNumbers.

    Declaration

    Objective-C

    - (NSArray *_Nullable)asNumbers;

    Swift

    func asNumbers() -> [Any]?
  • Split up ths 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.

    Declaration

    Objective-C

    - (NSArray<MaplyVectorObject *> *_Nonnull)splitVectors;

    Swift

    func splitVectors() -> [MaplyVectorObject]

    Return Value

    An NSArray of MaplyVectorObject.

  • 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.

    Declaration

    Objective-C

    - (void)subdivideToGlobe:(float)epsilon;

    Swift

    func subdivide(toGlobe epsilon: Float)
  • 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).

    Declaration

    Objective-C

    - (void)subdivideToGlobeGreatCircle:(float)epsilon;

    Swift

    func subdivide(toGlobeGreatCircle epsilon: Float)
  • 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.

    Declaration

    Objective-C

    - (void)subdivideToFlatGreatCircle:(float)epsilon;

    Swift

    func subdivide(toFlatGreatCircle epsilon: Float)
  • 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.

    Declaration

    Objective-C

    - (MaplyVectorObject *_Nonnull)tesselate;

    Swift

    func tesselate() -> MaplyVectorObject
  • 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.

    Declaration

    Objective-C

    - (MaplyVectorObject *_Nullable)clipToGrid:(CGSize)gridSize;

    Swift

    func clip(toGrid gridSize: CGSize) -> MaplyVectorObject?

    Return Value

    New areal features broken up along the grid.

  • 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.

    Declaration

    Objective-C

    - (MaplyVectorObject *_Nullable)clipToMbr:(MaplyCoordinate)ll
                                   upperRight:(MaplyCoordinate)ur;

    Swift

    func clip(toMbr ll: MaplyCoordinate, upperRight ur: MaplyCoordinate) -> MaplyVectorObject?

    Return Value

    The new areal features will be clipped along the bounding box.