Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions android/src/main/java/com/luggmaps/LuggPolygonView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class LuggPolygonView(context: Context) : ReactViewGroup(context) {
var coordinates: List<LatLng> = emptyList()
private set

var holes: List<List<LatLng>> = emptyList()
private set

var strokeColor: Int = Color.BLACK
private set

Expand All @@ -42,6 +45,10 @@ class LuggPolygonView(context: Context) : ReactViewGroup(context) {
coordinates = coords
}

fun setHoles(value: List<List<LatLng>>) {
holes = value
}

fun setStrokeColor(color: Int) {
strokeColor = color
}
Expand Down
21 changes: 21 additions & 0 deletions android/src/main/java/com/luggmaps/LuggPolygonViewManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,27 @@ class LuggPolygonViewManager :
}
}

@ReactProp(name = "holes")
override fun setHoles(view: LuggPolygonView, value: ReadableArray?) {
value?.let { array ->
val holesList = mutableListOf<List<LatLng>>()
for (i in 0 until array.size()) {
val holeArray = array.getArray(i)
val hole = mutableListOf<LatLng>()
if (holeArray != null) {
for (j in 0 until holeArray.size()) {
val coord = holeArray.getMap(j)
val lat = coord?.getDouble("latitude") ?: 0.0
val lng = coord?.getDouble("longitude") ?: 0.0
hole.add(LatLng(lat, lng))
}
}
holesList.add(hole)
}
view.setHoles(holesList)
}
}

@ReactProp(name = "strokeColor", customType = "Color")
override fun setStrokeColor(view: LuggPolygonView, value: Int?) {
view.setStrokeColor(value ?: android.graphics.Color.BLACK)
Expand Down
5 changes: 5 additions & 0 deletions android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ class GoogleMapProvider(private val context: Context) :

polygonView.polygon?.apply {
points = polygonView.coordinates
holes = polygonView.holes
fillColor = polygonView.fillColor
strokeColor = polygonView.strokeColor
strokeWidth = polygonView.strokeWidth.dpToPx()
Expand All @@ -565,6 +566,10 @@ class GoogleMapProvider(private val context: Context) :
.zIndex(polygonView.zIndex)
.clickable(true)

for (hole in polygonView.holes) {
options.addHole(hole)
}

val polygon = map.addPolygon(options)
polygonView.polygon = polygon
polygonToViewMap[polygon] = polygonView
Expand Down
22 changes: 22 additions & 0 deletions docs/POLYGON.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,27 @@ import { MapView, Polygon } from '@lugg/maps';
strokeWidth={2}
onPress={() => console.log('Polygon pressed')}
/>

{/* Polygon with a hole */}
<Polygon
coordinates={[
{ latitude: 37.790, longitude: -122.435 },
{ latitude: 37.790, longitude: -122.420 },
{ latitude: 37.775, longitude: -122.420 },
{ latitude: 37.775, longitude: -122.435 },
]}
holes={[
[
{ latitude: 37.787, longitude: -122.432 },
{ latitude: 37.787, longitude: -122.423 },
{ latitude: 37.778, longitude: -122.423 },
{ latitude: 37.778, longitude: -122.432 },
],
]}
fillColor="rgba(244, 67, 54, 0.3)"
strokeColor="#F44336"
strokeWidth={2}
/>
</MapView>
```

Expand All @@ -29,6 +50,7 @@ import { MapView, Polygon } from '@lugg/maps';
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `coordinates` | `Coordinate[]` | **required** | Array of coordinates forming the polygon boundary |
| `holes` | `Coordinate[][]` | - | Array of coordinate arrays representing interior holes |
| `fillColor` | `ColorValue` | - | Fill color of the polygon |
| `strokeColor` | `ColorValue` | - | Stroke (outline) color |
| `strokeWidth` | `number` | - | Stroke width in points |
Expand Down
11 changes: 7 additions & 4 deletions example/shared/src/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ function HomeContent() {
[]
);

const addMarker = () => {
const addMarker = (coordinate = lastCoordinate.current) => {
const type = randomFrom(MARKER_TYPES);
const id = Date.now().toString();

Expand All @@ -143,7 +143,7 @@ function HomeContent() {
{
id,
name: `marker-${id}`,
coordinate: lastCoordinate.current,
coordinate,
type,
anchor: { x: 0.5, y: type === 'icon' ? 1 : 0.5 },
text: randomLetter(),
Expand Down Expand Up @@ -190,7 +190,10 @@ function HomeContent() {
userLocationEnabled={locationPermission}
onReady={handleMapReady}
onPress={(e) => formatPressEvent(e, 'Press')}
onLongPress={(e) => formatPressEvent(e, 'Long press')}
onLongPress={(e) => {
formatPressEvent(e, 'Long press');
addMarker(e.nativeEvent.coordinate);
}}
onCameraMove={(e) => formatCameraEvent(e, false)}
onCameraIdle={(e) => formatCameraEvent(e, true)}
onMarkerPress={(e, m) => formatPressEvent(e, `Marker(${m.name})`)}
Expand Down Expand Up @@ -222,7 +225,7 @@ function HomeContent() {
>
<Text style={styles.statusText}>{statusText}</Text>
<View style={styles.sheetContent}>
<Button title="Add Marker" onPress={addMarker} />
<Button title="Add Marker" onPress={() => addMarker()} />
<Button
title={`Remove Marker (${markers.length})`}
onPress={removeRandomMarker}
Expand Down
37 changes: 32 additions & 5 deletions example/shared/src/components/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@ const CIRCLE_COORDS = Array.from({ length: 36 }, (_, i) => {
};
});

const HOLE_RADIUS = 0.0015;
const CIRCLE_HOLES = [
Array.from({ length: 36 }, (_, i) => {
const angle = (i * 10 * Math.PI) / 180;
return {
latitude: CIRCLE_CENTER.latitude + HOLE_RADIUS * Math.cos(angle),
longitude:
CIRCLE_CENTER.longitude +
(HOLE_RADIUS * Math.sin(angle)) /
Math.cos((CIRCLE_CENTER.latitude * Math.PI) / 180),
};
}),
];

const renderMarker = (
marker: MarkerData,
onPress?: (event: MarkerPressEvent, marker: MarkerData) => void,
Expand Down Expand Up @@ -234,6 +248,7 @@ export const Map = forwardRef<MapView, MapProps>(
<CrewMarker route={smoothedRoute} zoom={zoom} />
<Polygon
coordinates={CIRCLE_COORDS}
holes={CIRCLE_HOLES}
fillColor="rgba(66, 133, 244, 0.15)"
strokeColor="#4285F4"
strokeWidth={2}
Expand All @@ -246,7 +261,9 @@ export const Map = forwardRef<MapView, MapProps>(
color="#34A853"
/>
</MapView>
<Animated.View style={[styles.centerPin, centerPinStyle]} />
<Animated.View style={[styles.centerPin, centerPinStyle]}>
<View style={styles.centerPinDot} />
</Animated.View>
</View>
);
}
Expand All @@ -259,10 +276,20 @@ const styles = StyleSheet.create({
justifyContent: 'center',
},
centerPin: {
backgroundColor: 'blue',
height: 20,
width: 20,
borderRadius: 10,
alignItems: 'center',
justifyContent: 'center',
width: 32,
height: 32,
borderRadius: 16,
backgroundColor: 'rgba(66, 133, 244, 0.2)',
borderWidth: 2,
borderColor: 'white',
},
centerPinDot: {
width: 8,
height: 8,
borderRadius: 4,
backgroundColor: '#4285F4',
},
customMarker: {
height: 30,
Expand Down
1 change: 1 addition & 0 deletions ios/LuggPolygonView.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface LuggPolygonView : RCTViewComponentView

@property(nonatomic, readonly) NSArray<CLLocation *> *coordinates;
@property(nonatomic, readonly) NSArray<NSArray<CLLocation *> *> *holes;
@property(nonatomic, readonly) UIColor *strokeColor;
@property(nonatomic, readonly) UIColor *fillColor;
@property(nonatomic, readonly) CGFloat strokeWidth;
Expand Down
19 changes: 19 additions & 0 deletions ios/LuggPolygonView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ @interface LuggPolygonView () <RCTLuggPolygonViewViewProtocol>

@implementation LuggPolygonView {
NSArray<CLLocation *> *_coordinates;
NSArray<NSArray<CLLocation *> *> *_holes;
UIColor *_strokeColor;
UIColor *_fillColor;
CGFloat _strokeWidth;
Expand All @@ -36,6 +37,7 @@ - (instancetype)initWithFrame:(CGRect)frame {
_props = defaultProps;

_coordinates = @[];
_holes = @[];
_strokeColor = [UIColor blackColor];
_fillColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.3];
_strokeWidth = 1.0;
Expand All @@ -61,6 +63,19 @@ - (void)updateProps:(Props::Shared const &)props
}
_coordinates = [coords copy];

NSMutableArray<NSArray<CLLocation *> *> *holesArray = [NSMutableArray array];
for (const auto &hole : newViewProps.holes) {
NSMutableArray<CLLocation *> *holeCoords = [NSMutableArray array];
for (const auto &coord : hole) {
CLLocation *location =
[[CLLocation alloc] initWithLatitude:coord.latitude
longitude:coord.longitude];
[holeCoords addObject:location];
}
[holesArray addObject:[holeCoords copy]];
}
_holes = [holesArray copy];

if (newViewProps.strokeColor) {
UIColor *color = RCTUIColorFromSharedColor(newViewProps.strokeColor);
if (color) {
Expand Down Expand Up @@ -94,6 +109,10 @@ - (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask {
return _coordinates;
}

- (NSArray<NSArray<CLLocation *> *> *)holes {
return _holes;
}

- (UIColor *)strokeColor {
return _strokeColor;
}
Expand Down
46 changes: 43 additions & 3 deletions ios/core/AppleMapProvider.mm
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,19 @@ - (LuggPolygonView *)hitTestPolygonAtPoint:(CGPoint)point {
}
CGPathCloseSubpath(path);

BOOL contains = CGPathContainsPoint(path, NULL, mapPointAsCGP, NO);
for (NSArray<CLLocation *> *hole in polygonView.holes) {
for (NSUInteger j = 0; j < hole.count; j++) {
MKMapPoint mp = MKMapPointForCoordinate(hole[j].coordinate);
if (j == 0) {
CGPathMoveToPoint(path, NULL, mp.x, mp.y);
} else {
CGPathAddLineToPoint(path, NULL, mp.x, mp.y);
}
}
CGPathCloseSubpath(path);
}

BOOL contains = CGPathContainsPoint(path, NULL, mapPointAsCGP, YES);
CGPathRelease(path);

if (contains)
Expand Down Expand Up @@ -816,8 +828,11 @@ - (void)syncPolygonView:(LuggPolygonView *)polygonView {
for (NSUInteger i = 0; i < coordinates.count; i++) {
coords[i] = coordinates[i].coordinate;
}
NSArray<MKPolygon *> *interiorPolygons =
[self interiorPolygonsFromHoles:polygonView.holes];
MKPolygon *newPolygon = [MKPolygon polygonWithCoordinates:coords
count:coordinates.count];
count:coordinates.count
interiorPolygons:interiorPolygons];
free(coords);

polygonView.polygon = newPolygon;
Expand Down Expand Up @@ -853,15 +868,40 @@ - (void)addPolygonOverlayToMap:(LuggPolygonView *)polygonView {
coords[i] = coordinates[i].coordinate;
}

NSArray<MKPolygon *> *interiorPolygons =
[self interiorPolygonsFromHoles:polygonView.holes];
MKPolygon *polygon = [MKPolygon polygonWithCoordinates:coords
count:coordinates.count];
count:coordinates.count
interiorPolygons:interiorPolygons];
free(coords);

polygonView.polygon = polygon;
[_overlayToPolygonMap setObject:polygonView forKey:polygon];
[self insertOverlay:polygon withZIndex:polygonView.zIndex];
}

- (NSArray<MKPolygon *> *)interiorPolygonsFromHoles:
(NSArray<NSArray<CLLocation *> *> *)holes {
if (holes.count == 0)
return @[];

NSMutableArray<MKPolygon *> *interiorPolygons = [NSMutableArray array];
for (NSArray<CLLocation *> *hole in holes) {
if (hole.count == 0)
continue;
CLLocationCoordinate2D *holeCoords = (CLLocationCoordinate2D *)malloc(
sizeof(CLLocationCoordinate2D) * hole.count);
for (NSUInteger i = 0; i < hole.count; i++) {
holeCoords[i] = hole[i].coordinate;
}
MKPolygon *interiorPolygon = [MKPolygon polygonWithCoordinates:holeCoords
count:hole.count];
free(holeCoords);
[interiorPolygons addObject:interiorPolygon];
}
return [interiorPolygons copy];
}

- (void)insertOverlay:(id<MKOverlay>)overlay withZIndex:(NSInteger)zIndex {
if (zIndex == 0) {
[_mapView addOverlay:overlay];
Expand Down
15 changes: 15 additions & 0 deletions ios/core/GoogleMapProvider.mm
Original file line number Diff line number Diff line change
Expand Up @@ -562,13 +562,27 @@ - (void)syncPolygonView:(LuggPolygonView *)polygonView {
[path addCoordinate:location.coordinate];
}
polygon.path = path;
polygon.holes = [self holesPathsFromPolygonView:polygonView];
polygon.fillColor = polygonView.fillColor;
polygon.strokeColor = polygonView.strokeColor;
polygon.strokeWidth = polygonView.strokeWidth;
polygon.zIndex = (int)polygonView.zIndex;
polygon.tappable = polygonView.tappable;
}

- (NSArray<GMSPath *> *)holesPathsFromPolygonView:
(LuggPolygonView *)polygonView {
NSMutableArray<GMSPath *> *holePaths = [NSMutableArray array];
for (NSArray<CLLocation *> *hole in polygonView.holes) {
GMSMutablePath *holePath = [GMSMutablePath path];
for (CLLocation *location in hole) {
[holePath addCoordinate:location.coordinate];
}
[holePaths addObject:holePath];
}
return [holePaths copy];
}

- (void)processPendingPolygons {
if (!_mapView)
return;
Expand All @@ -589,6 +603,7 @@ - (void)addPolygonViewToMap:(LuggPolygonView *)polygonView {
}

GMSPolygon *polygon = [GMSPolygon polygonWithPath:path];
polygon.holes = [self holesPathsFromPolygonView:polygonView];
polygon.fillColor = polygonView.fillColor;
polygon.strokeColor = polygonView.strokeColor;
polygon.strokeWidth = polygonView.strokeWidth;
Expand Down
Loading