Skip to content

Commit

Permalink
Merge pull request #140 from hansemannn/feat/rounded-polyline
Browse files Browse the repository at this point in the history
feat: add rounded polyline support
  • Loading branch information
hansemannn authored Nov 12, 2020
2 parents 4aa3d67 + b85300d commit 8d9b658
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 2 deletions.
1 change: 1 addition & 0 deletions Classes/TiGooglemapsView.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ - (GMSMapView *)mapView
{
if (_mapView == nil) {
_mapView = [[GMSMapView alloc] initWithFrame:[self bounds]];
[_mapView setMapType:kGMSTypeNormal];
[_mapView setDelegate:self];
[_mapView setAutoresizingMask:UIViewAutoresizingNone];

Expand Down
8 changes: 8 additions & 0 deletions Classes/TiGooglemapsViewProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,14 @@
*/
- (void)showAnnotations:(id)annotations;

/**
* Draws a rounded polyline between two given coordiinates
*
* @param annotations The annotations to show.
* @since 5.5.0
*/
- (NSDictionary *)drawRoundedPolylineBetweenCoordinates:(id)args;

/**
* Returns all currently added annotations.
*
Expand Down
80 changes: 80 additions & 0 deletions Classes/TiGooglemapsViewProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#import "TiGooglemapsView.h"
#import "TiUtils.h"
#import "math.h"
#import <GoogleMaps/GMSGeometryUtils.h>

#import "GMUMarkerClustering.h"

Expand Down Expand Up @@ -781,6 +782,85 @@ - (void)showAnnotations:(id)args
}
}

// CREDITS: https://stackoverflow.com/a/53569754/5537752
- (NSDictionary *)drawRoundedPolylineBetweenCoordinates:(id)args
{
ENSURE_UI_THREAD(drawRoundedPolylineBetweenCoordinates, args);
ENSURE_SINGLE_ARG(args, NSDictionary)

// Unwrap proxy values
NSArray<NSDictionary<NSString *, NSNumber *> *> *coordinates = args[@"coordinates"];
NSDictionary *options = args[@"options"] ?: @{}; // UNUSED so far

NSDictionary<NSString *, NSNumber *> *startCoordinatesDictionary = coordinates[0];
NSDictionary<NSString *, NSNumber *> *endCoordinatesDictionary = coordinates[1];

CLLocationDegrees startLocationLatitude = [TiUtils doubleValue:startCoordinatesDictionary[@"latitude"]];
CLLocationDegrees startLocationLongitude = [TiUtils doubleValue:startCoordinatesDictionary[@"longitude"]];
CLLocationDegrees endLocationLatitude = [TiUtils doubleValue:endCoordinatesDictionary[@"latitude"]];
CLLocationDegrees endLocationLongitude = [TiUtils doubleValue:endCoordinatesDictionary[@"longitude"]];

CLLocationCoordinate2D startLocation = CLLocationCoordinate2DMake(startLocationLatitude, startLocationLongitude);
CLLocationCoordinate2D endLocation = CLLocationCoordinate2DMake(endLocationLatitude, endLocationLongitude);

// Create path
GMSMutablePath *path = [GMSMutablePath new];

CLLocationDistance distance = GMSGeometryDistance(startLocation, endLocation);
CLLocationCoordinate2D midPoint = GMSGeometryInterpolate(startLocation, endLocation, 0.5);

CLLocationDirection midToStartLocHeading = GMSGeometryHeading(midPoint, startLocation);

double controlPointAngle = 360.0 - (90.0 - midToStartLocHeading);
CLLocationCoordinate2D controlPoint = GMSGeometryOffset(midPoint, distance / 2.0 , controlPointAngle);

double stepper = 0.05;
NSMutableArray *range = [NSMutableArray arrayWithArray:@[]];

for (int i = 0.0; i < 1.0; i = i + 0.05) {
[range addObject:@(i)];
}

__block CLLocationCoordinate2D centerCoordinate;

[range enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
double t = obj.doubleValue;
double t1 = (1.0 - t);
CLLocationDegrees latitude = t1 * t1 * startLocation.latitude + 2 * t1 * t * controlPoint.latitude + t * t * endLocation.latitude;
CLLocationDegrees longitude = t1 * t1 * startLocation.longitude + 2 * t1 * t * controlPoint.longitude + t * t * endLocation.longitude;
CLLocationCoordinate2D point = CLLocationCoordinate2DMake(latitude, longitude);

if (idx == floor(range.count / 2)) {
centerCoordinate = point;
}

[path addCoordinate:point];
}];

// Draw polyline
GMSPolyline *polyline = [GMSPolyline polylineWithPath:path];
polyline.map = self.mapView.mapView; // Assign GMSMapView as map
polyline.strokeWidth = 2.0;

GMSStrokeStyle *greenToRed = [GMSStrokeStyle gradientFromColor:[UIColor clearColor] toColor:[UIColor blackColor]];
polyline.spans = @[[GMSStyleSpan spanWithStyle:greenToRed]];

GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:startLocation coordinate:endLocation];
UIEdgeInsets insets = UIEdgeInsetsMake(20, 20, 20, 20);

if ([TiUtils boolValue:@"animate" properties:options]) {
GMSCameraPosition *camera = [self.mapView.mapView cameraForBounds:bounds insets:insets];
[self.mapView.mapView animateToCameraPosition:camera];
} else {
[self.mapView.mapView moveCamera:[GMSCameraUpdate fitBounds:bounds withEdgeInsets:insets]];
}

return @{
@"latitude": @(centerCoordinate.latitude),
@"longitude": @(centerCoordinate.longitude)
};
}

- (NSArray<TiGooglemapsAnnotationProxy *> *)annotations
{
return markers;
Expand Down
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const maps = require('ti.googlemaps');
maps.setAPIKey('<YOUR_GOOGLE_MAPS_API_KEY>');
```

#### Use 100 % Cross-Platform with Android
#### Use Cross-Platform with Android

If you want to use this moduel as a replacement for Ti.Map on iOS, here is how you can have 100 % parity:
1. Create a file called `maps.js` in `app/lib/` (Alloy) or `Resources/` (Classic) with the following content
Expand Down Expand Up @@ -562,6 +562,17 @@ mapView.addPolyline(polyline);

You can get a list of all currently added polylines by using `mapView.polylines`;

##### Rounded Polylines

If you want rounded polylines (e.g. for simulating a flight direction), you can use the following method to draw the line:

```js
$.mapView.drawRoundedPolylineBetweenCoordinates({
coordinates: [ { latitude: 0.0, longitude: 0.0 }, { latitude: 1.0, longitude: 1.0 } ],
options: {} // Unused so far
});
```

#### Polygon

A polygon is a shape defined by its `points` property. It behaves similiar to a polyline, but is meant to close its area automatically and also supports the `fillColor` property.
Expand Down
2 changes: 1 addition & 1 deletion manifest
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# this is your module manifest and used by Titanium
# during compilation, packaging, distribution, etc.
#
version: 5.4.1
version: 5.5.0
apiversion: 2
architectures: armv7 arm64 i386 x86_64
description: ti.googlemaps
Expand Down

0 comments on commit 8d9b658

Please sign in to comment.