System requirements
With the Ramani API Framework for iOS, you can build apps that target native 32-bit or 64-bit devices running iOS 9.0 and later.
Developing an application with the Ramani API Framework for iOS requires the following:
- Xcode 9.0 or later.
- iOS SDK 11.0 or later (up to 11.0).
- Google Maps SDK 3.0 or later.
Screen captures
Core functionality
- Objective-C Library
- Access online map data through various RAMANI Services
- Support for Google Maps Services
- Georeference information from the COPERNICUS and Sentinel data services
- Store and Get geometry data in Ramani Cloud
Sample Project
To get All the samples source code, you can clone or download on this Project RamaniiOSTest
Getting started
These instructions will help you how to development with our Maps-API in your project. See descriptions below for our Maps-API.
Install And Import RamaniAPi POD Library
The Maps SDK for iOS is available as a CocoaPods pod. CocoaPods is an open source dependency manager for Swift and Objective-C Cocoa projects. If you don’t already have the CocoaPods tool, install it on macOS by running the following command from the terminal. For details, see the CocoaPods Getting Started guide. Here is the way how to install SDK into your project
- Type
sudo gem install cocoapods
in terminal. - Create a file named Podfile in your project directory. This file defines your project’s dependencies. Or you can get
podfile
automatically by open a terminal and go to the directory containing the project :
cd <path-to-project>
then type pod init
in terminal, the podfile
will automatically available in your project file
- Edit the Podfile and add your dependencies. Here is an example which includes the dependencies you need for the Maps SDK for iOS and Places SDK for iOS (optional):
source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!
target 'RamaniiOSTest' do
pod 'GoogleMaps'
pod 'RamaniApi', :git => 'https://team.ujuizi.com:6443/RAMANI/iospods.git', :tag => '2.0.0'
end
post_install do |installer|
installer.aggregate_targets.each do |aggregate_target|
if aggregate_target.name == 'Pods-RamaniiOSTest'
aggregate_target.xcconfigs.each do |config_name, config_file|
aggregate_target.pod_targets.each do |pod_target|
pod_target.specs.each do |spec|
if spec.attributes_hash['vendored_frameworks'] != nil or (spec.attributes_hash['ios'] != nil and spec.attributes_hash['ios']['vendored_frameworks'] != nil)
frameworkPaths = unless spec.attributes_hash['ios'].nil? then spec.attributes_hash['ios']['vendored_frameworks'] else spec.attributes_hash['vendored_frameworks'] end || Set.new
frameworkNames = Array(frameworkPaths).map(&:to_s).map do |filename|
extension = File.extname filename
File.basename filename, extension
end
frameworkNames.each do |name|
puts "Removing #{name} from OTHER_LDFLAGS"
config_file.frameworks.delete(name)
end
end
end
end
xcconfig_path = aggregate_target.xcconfig_path(config_name)
config_file.save_as(xcconfig_path)
end
end
end
end
- Don’t forget to change YOUR_PROJECT_NAME to your project name
- Save the Podfile.
- Run the pod install command. This will install the APIs specified in the Podfile, along with any dependencies they may have.
- Before using RamaniApi code, don’t forget add
import RamaniApi
on your Swift code, or add#import <Ramani/RSMapServices.h>
on your Objective-C code.
Import RamaniApi using Library File
Follow the step bellow to implement our library into your project :
- Download and extract the newest framework library (RamaniAPI iOS 2.0.1)
- Create new project or open your own project that you want to implement the framework library
-
Drag and drop the library that you’ve downloaded before inside your project, or you can do it in another way, you can go to :
build phase
link binary with libraries
- click
+
button to add the framework library or click-
button to remove the framework library
- Create
.h
file inside your project, name it [your project name]-Bridging-Header.h - Import Framework library into [your project name]-Bridging-Header.h file
- Make sure your Briding-Header file already registered on your Project Build Settings>Objective-C Bridging Header (see This Insctructions)
#ifndef [your\_project\_name]\_Bridging\_Header\_h
#define [your\_project\_name]\_Bridging\_Header\_h
#endif /\* [your\_project\_name]\_Bridging\_Header\_h \*/
#import <RamaniApi/RSMapServices.h>
#import <RamaniApi/RSSyncTileLayer.h>
- Make sure your Google Maps are showing by following this instructions
API-Key
You must provide the API-Key that you get from our client-area webpage before accessing our services. Below is the step-by-step guide to create new API Key:
- Sign in. Or Register first, if you don't have an account yet
- Login to your dashboard.
- Select tab Configuration and your API Key is there.
Add API Key on Your Code
After you get your API Key, add your API key to your AppDelegate.swift :
- Add the following to your
application(_:didFinishLaunchingWithOptions:)
method, replacing YOUR_API_KEY with your API key, and YOUR_USERNAME with your username (see API KEY):
RSMapServices.apiKey("YOUR_API_KEY", userName: "YOUR_USERNAME", schema: "public")
Note:
-
public
is the default Schema name.
Sample Codes
Get Ramani Public Layer ID
- Goto Ramani Public Maps
- Click on layer button.
- Select the datasets you want to use.
- Login if you are not loggin yet.
- Draw something on the map.
- Click
get code
button. - You will see the Layer ID and also some code snippet.
- For sample
public.username_SWTRR
.
Get Private Layer ID
- Login to your Ramani Cloud Account
- Click Editor button from your dashboard.
- Select the Database tab.
- The Layer ID is combination of Schema and Table ID, here you schema name.
- This is your layer ID.
- For sample
public.SWTRR
.
Load Map Layer (using layerID)
With the Ramani API Framework for iOS, you can add a Map Layer to your application. The code below demonstrates how to add a map layer to an existing ViewController.
import RamaniApi //add this
class YourViewController {
private var mapView_: GMSMapView?
let layerId = "ddl.simS3seriesCoverGlobal.coverclass"
override func loadView() {
let camera = GMSCameraPosition.camera(withLatitude: 0, longitude: 0, zoom: 8)
mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
mapView?.isMyLocationEnabled = true
// set this for Tap up Event on Map
mapView?.delegate = self
view = mapView
///create map tile layer
let tileLayer :RSSyncTileLayer = RSMapServices.getMap("LayerID") as! RSSyncTileLayer
tileLayer.map = mapView
}
}
Load Map Layer (using Ramani Analytics URL)
If you are using Ramani Analytics URL, the usage is the same as layerID.
But sometimes, the url can be too long. Therefore, you can use the shorten URL by clicking Get Maps-API Endpoint on your OPeNDAP URL page, Data Files section. And then, copy the URL.
// Global Night time Lights sentinel 3 https://analytics.ramani.ujuizi.com/goto/d831a7cc7346e63ca861ec6748450d4d
//Add opendap URL here and add .wms at the end of URL
let params = ["dataset": "https://analytics.ramani.ujuizi.com/goto/d831a7cc7346e63ca861ec6748450d4d
Get Location Info (getPoint)
To get more features information at a single point. Retrieves data, including geometry and attribute values.
let coordinate = CLLocationCoordinate2D(latitude: 47.18224592701491, longitude: 8.581695556640627);
let pointInfo = RSMapServices.getPoint(coordinate, layerID: "YOUR_LAYERID")
print("pointInfo : \(String(describing: pointInfo))")
<i>Note</i>: The getPoint operation is designed to provide clients with more information about a single location on a map.
Get Vertical Profile
To get more features information at a single point(Get Point), along a vertical dimension.
let coordinate = CLLocationCoordinate2D(latitude: 47.18224592701491, longitude: 8.581695556640627);
let getVerticleProfile = RSMapServices.getVerticleProfileJson(coordinate, layerID: "YOUR_LAYERID");
print("getVerticleProfile : (String(describing: getVerticleProfile))");
Note:
- Only works on layers that have a temporal dimension (explore the maps we have offer in our DDL), for example nitrates in the depth of the ocean
- Only support for JSON, PNG, and SVG.
- To get layer capabilities (attribute) or if you want to set custom parameter.
Get Time-series Profile
To get more features information at a single point(Get Point), along with variation in time (along a temporal dimension).
let coordinate = CLLocationCoordinate2D(latitude: 47.18224592701491, longitude: 8.581695556640627);
var params = ["TIME": "2010-02-04T00:00:00.000Z/2010-04-15T00:00:00.000Z"]
RSMapServices.params = params
let getTimeSeriesProfile = RSMapServices.getTimeseriesProfileJson(coordinate, layerID: "YOUR_LAYERID");
print("getTimeSeriesProfile : (String(describing: getTimeSeriesProfile))");
Note:
- Only works on layers that have a temporal dimension (explore the maps we have offer in our DDL), for example Leaf Area Index (LAI) over the seasons of the year
- Only support for JSON, PNG, and SVG.
- To get layer capabilities (attribute) or if you want to set custom parameter.
Get Horizontal Profile (GetTransect)
To get more features information at multiple point, along a horizontal dimension. For example, atmospheric ozone along a line (single or multiple segments) crossing a city.
private var arrayCoordinates = NSMutableArray(array:
[
CLLocation(latitude: 8.134002685546877 , longitude: 47.23542209101768),
CLLocation(latitude: 8.489685058593752 , longitude: 47.32579231609051),
])
let getTransect = RSMapServices.getTransectJson(arrayCoordinates, layerID: "YOUR_LAYERID");
print("getTransect : (String(describing: getTransect))");
Note:
- Only support for JSON, PNG, SVG.
- Explore the maps we have offer in our DDL.
- To get layer capabilities (attribute) or if you want to set custom parameter.
Get Area Profile
To get more features information at multiple point, along a horizontal dimension. But for an area defined by PolygonOptions.
private var arrayCoordinates = NSMutableArray(array:
[
CLLocation(latitude: 8.661346435546877 , longitude: 47.28295557691233),
CLLocation(latitude: 8.661346435546877 , longitude: 47.32951560950959),
CLLocation(latitude: 8.672332763671797 , longitude: 47.28295557691233),
CLLocation(latitude: 8.720397949218793 , longitude: 47.33603074146188),
CLLocation(latitude: 8.740997314453045 , longitude: 47.28295557691233),
CLLocation(latitude: 8.760223388671877 , longitude: 47.3164829342833),
CLLocation(latitude: 8.760223388671877 , longitude: 47.3164829342833),
])
let areaJSON = RSMapServices.getAreaJson(arrayCoordinates, layerID: "YOUR_LAYERID", returnType: "aggregate")
print("areaJSON : (String(describing: areaJSON))");
Note:
- Only support for JSON, PNG, SVG.
- Only support for dataType : ALL, HISTOGRAM, and AGGREGATE.
- Explore the maps we have offer in our DDL.
- To get layer capabilities (attribute) or if you want to set custom parameter.
Return Example :
{
"type": "GetAreaResponse",
"area": {
"crs": "EPSG:4326",
"linestring": "3.53759765625 47.79839667295524,4.556673569110679 48.07338898931344,3.4914556008582487 47.49998727341379,5.2789456005429924 47.913809258555474,3.3776305571161824 46.756562106822706,5.6348949137565185 47.21247952521911,3.787219268892672 46.519273910457045,4.775344730497775 46.848707252177114,4.775344730497775 46.848707252177114,",
"dataset": "Sentinel-3: Global Nighttime Lights",
"variable": "Nighttime Lights",
"units": "",
"aggregate": {
"mean": 6.622666666666683,
"stdv": 8.875178801281983,
"skew": 2.6443954084095673,
"kurt": 9.388449667730299,
"min": 0,
"max": 61,
"perc": 6,
"median": 6
},
"histogram": [
"{frequency=2.0, value=54.0}",
"{frequency=1.0, value=56.0}",
...
"{frequency=2.0, value=16.0}",
"{frequency=1.0, value=15.0}",
"{frequency=2.0, value=18.0}"
]
}
}
Get Point Cube
The extended version of Get Feature Info (Get Point). Where you’re able to not just get the information on a single point, but also the information of the neighboor GeoPoint, in a 3x3, 5x5, etc bounding box. It would be usefull for a comparison (e.g temperature between all neighboring pixels in a 3x3).
In order to create a grid(rectangular), a bounding box is needed. And every bounding box has a radius, which is the distance from your center point to the outer edge of bounding box. And the diameter, which is the distance between outer edge, or always twice the radius.
The radius value in our API is the latlong distance(e.g. distance from GeoPoint(10.00, 10.00) to GeoPoint(10.00, 10.50) will has 0.5 distance in lon (± 50Km)). And if you set your radius at 0.5, your diameter(grid width) will be 1. This also means, the distance between bounding box center point in your grid, is 1 (diameter).
let coordinate = CLLocationCoordinate2D(latitude: 47.18224592701491, longitude: 8.581695556640627);
let radius = Int32(1)
let gridSize = Int32(3) // supports >=3
let pointCube = RSMapServices.getPointCubeJson(coordinate, layerID: "YOUR_LAYERID", grid: gridSize , radius: radius)
print("pointCube : (String(describing: pointCube))");
The code above will give you 9 data points, since you're requesting for 3x3 grid size. The value itself once again, depend on your GeoPoint and Radius.
You tapped at 8.581695556640627, 47.18224592701491
featureInfo JSON : {
"success" : 1,
"data" : [
{
"type" : "FeatureInfoResponse",
"features" : [
{
"geometry" : "8.581695556640627 47.18224592701491",
"properties" : {
"gridCentreLon" : 8.581695556640627,
"jIndex" : 45426,
"iIndex" : 117396,
"gridCentreLat" : 47.18224592701491
},
"featureInfo" : [
{
"value" : 14,
"time" : "2009-01-01T00:00:00.000Z"
}
]
}
]
},
....
]
}
With the order from the Bottom Left (the lowest coordinate) to Top Right (the higher coordinate). Below is the visualization of the 3x3 grid indices, where the (0,0) is your original GeoPoint:
Note:
- Only support for grid size with odd value and >= 3
- Explore the maps we have offer in our DDL
Get Layer Attributes(GetMetadata)
To requests metadata (e.g. date-range, layer details, units, etc.) from layer dataset. For example, to obtain the temporal range of a time-series required by getTimeseriesProfile use (TIME
), or to get the extremes of a layer (Min
), and (Max
) to set the scaleRange parameter.
var getMetadata = RSMapServices.getMetadata(layerId)
Note:
- Only support JSON.
- For more information about which parameters you can get follow this link.
- Explore the maps we have offer in our DDL.
Get dates for timeseries and return as RSS
Using Get Layer Attributes method, below is the example to get (TIME
) for Get Time-series Profile:
var params = ["item": "dates", "format": "rss"]
RSMapServices.params = params
var getMetadata = RSMapServices.getMetadata(layerID)
Get dates for timeseries and return ISO8601 format
Using Get Layer Attributes method, below is the example to get (TIME
) for Get Time-series Profile:
var params = ["item": "dates"]
RSMapServices.params = params
var getMetadata = RSMapServices.getMetadata(layerID)
Note:
- Only support JSON.
- For more information about which parameters you can get follow this link.
- Explore the maps we have offer in our DDL.
Set Layer Attributes (setParams)
Set Parameter is used to add or replace existing parameters, to make your requested data richer and more dynamic. Make sure to call setParams(params)
before executing your request, or the API will use your default parameter.
var params = ["TIME": "2010-02-04T00:00:00.000Z/2010-04-15T00:00:00.000Z"]
RSMapServices.params = params
var img: UIImage? = RSMapServices.getTimeseriesProfile(coordinate, layerID: layerID)
var myImageView = UIImageView(image: img)
view.addSubview(myImageView)
- The example above use param (
TIME
) to set the temporal range of a time-series. - For more information about which parameters you can set, follow this link.
- Explore the maps we have offer in our DDL.
Manipulate Your Data in Our Cloud
With this method, you can do CRUD (Create, Read, Update, Delete) to your dataset. The first example shows how to search for a feature in a layer and show it on the map, the second shows how to insert a new point (i.e. GPS-location).
var yourdata = RSMapServices.sqlAPI("SELECT * FROM [schemaName].[layerID] WHERE round(ST_Distance(ST_Transform(\"the_geom\",3857),
'ST_GeomFromText('POINT(551569.5961058318 6701998.640044251)',3857))) < 6114.9622628
ORDER BY round(ST_Distance(ST_Transform(\"the_geom\",3857),
ST_GeomFromText('POINT(551569.5961058318 6701998.640044251)',3857)))LIMIT 5");
print(yourdata)
- Basically, you're using PostgreSQL query syntax
- Only work for dataset/layer under your account(private)
- Explore the maps we have offer in our DDL.
Store Geometry Data
Store your single point or multiple point such as linestring, polygon on our Cloud Service as Geometry data.
let coordinate = CLLocationCoordinate2D(latitude: 47.18224592701491, longitude: 8.581695556640627);
var fields = ["id": "100", "time": "1434159945524", "accelx": "4.338"]
RSMapServices.storePoint(layerID, fields: fields, coordinate: coordinate)
var fields = ["id": "100", "time": "1434159945524", "accelx": "4.338"]
RSMapServices.storeLine(coordinates, layerID: layerID, fields: fields)
var fields = ["id": "100", "time": "1434159945524", "accelx": "4.338"]
RSMapServices.storePolygon(coordinates, layerID: layerID, fields: fields)
- Only work for dataset/layer under your account(private)
- If you do not have any dataset in your account, in your account go to
Editor >> Database
<!--
See Also
-->
License
Copyright (c) 2017 RAMANI B.V.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.