Skip to content
This repository was archived by the owner on Jan 31, 2022. It is now read-only.

Commit cc92bf5

Browse files
authored
Query: Updates to insidePolygon and insideBoundingBox (#229)
* Query: Migrate insidePolygon to handle several polygons * Query: Update documentation for insideBoundingBox [ci skip] * Query: Catch eventual NFEs in getInsidePolygon
1 parent 50da993 commit cc92bf5

File tree

2 files changed

+109
-27
lines changed

2 files changed

+109
-27
lines changed

algoliasearch/src/main/java/com/algolia/search/saas/Query.java

Lines changed: 98 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -618,12 +618,8 @@ public int hashCode() {
618618
private static final String KEY_INSIDE_BOUNDING_BOX = "insideBoundingBox";
619619

620620
/**
621-
* Search for entries inside a given area defined by the two extreme points
622-
* of a rectangle. At indexing, geoloc of an object should be set with
623-
* _geoloc attribute containing lat and lng attributes (for example
624-
* {"_geoloc":{"lat":48.853409, "lng":2.348800}})
625-
* <p>
626-
* You can use several bounding boxes (OR) by calling this method several times.
621+
* Search for entries inside one area or the union of several areas
622+
* defined by the two extreme points of a rectangle.
627623
*/
628624
public @NonNull Query setInsideBoundingBox(@Nullable GeoRect... boxes) {
629625
if (boxes == null) {
@@ -674,19 +670,46 @@ public int hashCode() {
674670
}
675671
}
676672

677-
private static final String KEY_INSIDE_POLYGON = "insidePolygon";
678-
679673
/**
680-
* Add a point to the polygon of geo-search (requires a minimum of three points to define a valid polygon)
681-
* At indexing, you should specify geoloc of an object with the _geoloc attribute (in the form "_geoloc":{"lat":48.853409, "lng":2.348800} or
682-
* "_geoloc":[{"lat":48.853409, "lng":2.348800},{"lat":48.547456, "lng":2.972075}] if you have several geo-locations in your record).
674+
* A polygon in geo coordinates.
675+
* Used in geo-search.
683676
*/
684-
public @NonNull Query setInsidePolygon(@Nullable LatLng... points) {
685-
if (points == null) {
686-
set(KEY_INSIDE_POLYGON, null);
687-
} else if (points.length < 3) {
688-
throw new IllegalArgumentException("A polygon must have at least three vertices");
689-
} else {
677+
public static final class Polygon {
678+
@NonNull
679+
public final LatLng[] points;
680+
681+
public Polygon(@NonNull LatLng... points) {
682+
if (points.length < 3) {
683+
throw new IllegalArgumentException("A polygon must have at least three vertices");
684+
}
685+
this.points = points;
686+
}
687+
688+
public Polygon(String value) {
689+
this(parse(value));
690+
}
691+
692+
public Polygon(Polygon other) {
693+
this.points = other.points;
694+
}
695+
696+
@Override public boolean equals(Object o) {
697+
if (this == o) {
698+
return true;
699+
}
700+
if (o == null || getClass() != o.getClass()) {
701+
return false;
702+
}
703+
704+
Polygon polygon = (Polygon) o;
705+
return Arrays.equals(points, polygon.points);
706+
}
707+
708+
@Override public int hashCode() {
709+
return Arrays.hashCode(points);
710+
}
711+
712+
@Override public String toString() {
690713
StringBuilder sb = new StringBuilder();
691714
for (LatLng point : points) {
692715
if (sb.length() != 0) {
@@ -696,14 +719,10 @@ public int hashCode() {
696719
sb.append(',');
697720
sb.append(point.lng);
698721
}
699-
set(KEY_INSIDE_POLYGON, sb.toString());
722+
return sb.toString();
700723
}
701-
return this;
702-
}
703724

704-
public @Nullable LatLng[] getInsidePolygon() {
705-
try {
706-
String value = get(KEY_INSIDE_POLYGON);
725+
public static @Nullable Polygon parse(String value) {
707726
if (value != null) {
708727
String[] fields = value.split(",");
709728
if (fields.length % 2 == 0 && fields.length / 2 >= 3) {
@@ -714,10 +733,65 @@ public int hashCode() {
714733
Double.parseDouble(fields[2 * i + 1])
715734
);
716735
}
717-
return result;
736+
return new Polygon(result);
718737
}
719738
}
720739
return null;
740+
}
741+
}
742+
743+
private static final String KEY_INSIDE_POLYGON = "insidePolygon";
744+
745+
/**
746+
* Search for entries inside a given area defined by the points of a polygon.
747+
*/
748+
public @NonNull Query setInsidePolygon(@Nullable LatLng... points) {
749+
set(KEY_INSIDE_POLYGON, points == null ? null : new Polygon(points).toString());
750+
return this;
751+
}
752+
753+
/**
754+
* Search for entries inside a given area defined by several polygons.
755+
*/
756+
public @NonNull Query setInsidePolygon(@Nullable Polygon... polygons) {
757+
String insidePolygon = null;
758+
if (polygons == null) {
759+
insidePolygon = null;
760+
} else if (polygons.length == 1) {
761+
insidePolygon = polygons[0].toString();
762+
} else {
763+
for (Polygon polygon : polygons) {
764+
String polygonStr = "[" + polygon + "]";
765+
if (insidePolygon == null) {
766+
insidePolygon = "[";
767+
} else {
768+
insidePolygon += ",";
769+
}
770+
insidePolygon += polygonStr;
771+
}
772+
insidePolygon += "]";
773+
}
774+
set(KEY_INSIDE_POLYGON, insidePolygon);
775+
return this;
776+
}
777+
778+
public @Nullable Polygon[] getInsidePolygon() {
779+
try {
780+
String value = get(KEY_INSIDE_POLYGON);
781+
Polygon[] polygons;
782+
if (value == null) {
783+
return null;
784+
} else if (value.startsWith("[")) {
785+
String[] values = parseArray(value);
786+
polygons = new Polygon[values.length];
787+
for (int i = 0; i < values.length; i++) {
788+
polygons[i] = new Polygon(values[i].replace("[", "").replace("]", ""));
789+
}
790+
return polygons;
791+
} else {
792+
final Polygon polygon = Polygon.parse(value);
793+
return new Polygon[]{polygon};
794+
}
721795
} catch (NumberFormatException e) {
722796
return null;
723797
}

algoliasearch/src/test/java/com/algolia/search/saas/QueryTest.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -563,11 +563,19 @@ public void insideBoundingBox() {
563563
public void insidePolygon() {
564564
Query query = new Query();
565565
assertNull(query.getInsidePolygon());
566-
final Query.LatLng[] box = { new Query.LatLng(11.111111, 22.222222), new Query.LatLng(33.333333, 44.444444), new Query.LatLng(-55.555555, -66.666666) };
567-
query.setInsidePolygon(box);
568-
assertArrayEquals(box, query.getInsidePolygon());
566+
final Query.Polygon polygon = new Query.Polygon(new Query.LatLng(11.111111, 22.222222), new Query.LatLng(33.333333, 44.444444), new Query.LatLng(-55.555555, -66.666666));
567+
Query.Polygon[] polygons = {polygon};
568+
query.setInsidePolygon(polygons);
569+
assertArrayEquals(polygons, query.getInsidePolygon());
569570
assertEquals("11.111111,22.222222,33.333333,44.444444,-55.555555,-66.666666", query.get("insidePolygon"));
570571
assertArrayEquals(query.getInsidePolygon(), Query.parse(query.build()).getInsidePolygon());
572+
573+
final Query.Polygon polygon2 = new Query.Polygon(new Query.LatLng(77.777777, 88.888888), new Query.LatLng(99.999999, 11.111111), new Query.LatLng(-11.111111, -22.222222));
574+
polygons = new Query.Polygon[]{polygon, polygon2};
575+
query.setInsidePolygon(polygons);
576+
assertArrayEquals(polygons, query.getInsidePolygon());
577+
assertEquals("[[11.111111,22.222222,33.333333,44.444444,-55.555555,-66.666666],[77.777777,88.888888,99.999999,11.111111,-11.111111,-22.222222]]", query.get("insidePolygon"));
578+
assertArrayEquals(query.getInsidePolygon(), Query.parse(query.build()).getInsidePolygon());
571579
}
572580

573581
@Test

0 commit comments

Comments
 (0)