Skip to content

Commit

Permalink
make it possible to show the quest markers at the ends of the geometr…
Browse files Browse the repository at this point in the history
…y instead of the center (implement #733)
  • Loading branch information
westnordost committed Dec 2, 2018
1 parent 29082af commit d7ad909
Show file tree
Hide file tree
Showing 21 changed files with 149 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void testAddGet()
Quest q2 = dao.get(id);

assertEquals(q.getId(), q2.getId());
assertEquals(q.getMarkerLocation(), q2.getMarkerLocation());
assertEquals(q.getCenter(), q2.getCenter());
assertEquals(q.getStatus(), q2.getStatus());
}

Expand Down Expand Up @@ -181,7 +181,7 @@ private static Quest createQuest(long id, long lastUpdate, QuestStatus status)
when(quest.getId()).thenReturn(id);
when(quest.getStatus()).thenReturn(status);
when(quest.getLastUpdate()).thenReturn(new Date(lastUpdate));
when(quest.getMarkerLocation()).thenReturn(new OsmLatLon(0,0));
when(quest.getCenter()).thenReturn(new OsmLatLon(0,0));
return quest;
}

Expand All @@ -190,7 +190,7 @@ private static Quest createQuest(long id, double lat, double lon, QuestStatus st
Quest quest = mock(Quest.class);
when(quest.getStatus()).thenReturn(status);
when(quest.getId()).thenReturn(id);
when(quest.getMarkerLocation()).thenReturn(new OsmLatLon(lat,lon));
when(quest.getCenter()).thenReturn(new OsmLatLon(lat,lon));
when(quest.getLastUpdate()).thenReturn(new Date());
return quest;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ public TestQuestDao(SQLiteOpenHelper dbHelper)

insert.bindLong(1, quest.getId());
insert.bindString(2, quest.getStatus().name());
insert.bindDouble(3, quest.getMarkerLocation().getLatitude());
insert.bindDouble(4, quest.getMarkerLocation().getLongitude());
insert.bindDouble(3, quest.getCenter().getLatitude());
insert.bindDouble(4, quest.getCenter().getLongitude());
insert.bindDouble(5, quest.getLastUpdate().getTime());

return insert.executeInsert();
Expand All @@ -75,8 +75,8 @@ public TestQuestDao(SQLiteOpenHelper dbHelper)
{
ContentValues v = new ContentValues();
v.put(ID_COL, quest.getId());
v.put(LAT_COL, quest.getMarkerLocation().getLatitude());
v.put(LON_COL, quest.getMarkerLocation().getLongitude());
v.put(LAT_COL, quest.getCenter().getLatitude());
v.put(LON_COL, quest.getCenter().getLongitude());
return v;
}

Expand All @@ -91,7 +91,7 @@ public static Quest createQuest(long id, double lat, double lon, QuestStatus sta
Quest quest = mock(Quest.class);
when(quest.getStatus()).thenReturn(status);
when(quest.getId()).thenReturn(id);
when(quest.getMarkerLocation()).thenReturn(new OsmLatLon(lat,lon));
when(quest.getCenter()).thenReturn(new OsmLatLon(lat,lon));
when(quest.getLastUpdate()).thenReturn(new Date(time));
return quest;
}
Expand All @@ -118,4 +118,4 @@ public TestDbHelper(Context context)

}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ private void checkEqual(OsmQuest quest, OsmQuest dbQuest)
assertEquals(quest.getChanges(), dbQuest.getChanges());
assertEquals(quest.getChangesSource(), dbQuest.getChangesSource());
assertEquals(quest.getGeometry(), dbQuest.getGeometry());
assertEquals(quest.getMarkerLocation(), dbQuest.getMarkerLocation());
assertEquals(quest.getCenter(), dbQuest.getCenter());
// is now updated to current time on DB insert
// no: assertEquals(quest.getLastUpdate(), dbQuest.getLastUpdate());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ private void checkEqual(OsmNoteQuest quest, OsmNoteQuest dbQuest)
{
assertEquals(quest.getLastUpdate(), dbQuest.getLastUpdate());
assertEquals(quest.getStatus(), dbQuest.getStatus());
assertEquals(quest.getMarkerLocation(), dbQuest.getMarkerLocation());
assertEquals(quest.getCenter(), dbQuest.getCenter());
assertEquals(quest.getComment(), dbQuest.getComment());
assertEquals(quest.getId(), dbQuest.getId());
assertEquals(quest.getType(), dbQuest.getType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ private void showQuestSolvedAnimation(Quest quest, String source)
int size = (int) DpUtil.toPx(42, this);
int[] offset = new int[2];
mapFragment.getView().getLocationOnScreen(offset);
PointF startPos = mapFragment.getPointOf(quest.getMarkerLocation());
PointF startPos = mapFragment.getPointOf(quest.getCenter());
startPos.x += offset[0] - size/2;
startPos.y += offset[1] - size*1.5;
showMarkerSolvedAnimation(quest.getType().getIcon(), startPos, source);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ public interface Quest
Long getId();
void setId(long id);

LatLon getMarkerLocation();
LatLon getCenter();
LatLon[] getMarkerLocations();
ElementGeometry getGeometry();

QuestType getType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public boolean createNote(long osmQuestId, String questTitle, String text, Array
if(q == null || q.getStatus() != QuestStatus.NEW) return false;

CreateNote createNote = new CreateNote();
createNote.position = q.getMarkerLocation();
createNote.position = q.getCenter();
createNote.text = text;
createNote.questTitle = questTitle;
createNote.elementType = q.getElementType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ public abstract class AOsmElementQuestType implements OsmElementQuestType
@NonNull @Override public Countries getEnabledForCountries() { return Countries.ALL; }
@Override public void cleanMetadata() { }
@Override public int getTitle() { return getTitle(Collections.emptyMap()); }
@Override public boolean hasMarkersAtEnds() { return false; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,7 @@ public interface OsmElementQuestType extends QuestType

/** The quest type can clean it's metadata here, if any */
void cleanMetadata();

/** @return whether the markers should be at the ends instead of the center */
boolean hasMarkersAtEnds();
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import android.support.annotation.Nullable;

import java.util.Date;
import java.util.List;

import de.westnordost.streetcomplete.data.Quest;
import de.westnordost.streetcomplete.data.QuestStatus;
import de.westnordost.streetcomplete.data.osm.changes.StringMapChanges;
import de.westnordost.streetcomplete.data.QuestType;
import de.westnordost.osmapi.map.data.Element;
import de.westnordost.osmapi.map.data.LatLon;
import de.westnordost.streetcomplete.util.SphericalEarthMath;

/** Represents one task for the user to complete/correct the data based on one OSM element */
public class OsmQuest implements Quest
Expand Down Expand Up @@ -56,7 +58,24 @@ public OsmQuest(Long id, OsmElementQuestType type, Element.Type elementType, lon
return id;
}

@Override public LatLon getMarkerLocation()
@Override public LatLon[] getMarkerLocations()
{
if(getOsmElementQuestType().hasMarkersAtEnds() && geometry.polylines != null)
{
List<LatLon> polyline = geometry.polylines.get(0);
double length = SphericalEarthMath.distance(polyline);
if(length > 15*4)
{
return new LatLon[]{
SphericalEarthMath.pointOnPolylineFromStart(polyline, 15),
SphericalEarthMath.pointOnPolylineFromEnd(polyline, 15),
};
}
}
return new LatLon[]{getCenter()};
}

@Override public LatLon getCenter()
{
return geometry.center;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ public OsmNoteQuest(Long id, Note note, QuestStatus status, String comment, Date
return id;
}

@Override public LatLon getMarkerLocation()
@Override public LatLon[] getMarkerLocations()
{
return note.position;
return new LatLon[]{note.position};
}

@Override public ElementGeometry getGeometry()
Expand All @@ -79,7 +79,12 @@ public OsmNoteQuest(Long id, Note note, QuestStatus status, String comment, Date
// will/should likely not show up for other users of this app

// no geometry other than the marker location
return new ElementGeometry(getMarkerLocation());
return new ElementGeometry(getCenter());
}

@Override public LatLon getCenter()
{
return note.position;
}

public Note getNote()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Note uploadNoteChanges(OsmNoteQuest quest)

private static String getNoteQuestStringForLog(OsmNoteQuest n)
{
LatLon pos = n.getMarkerLocation();
LatLon pos = n.getCenter();
return "\"" + n.getComment() + "\" at " + pos.getLatitude() + ", " + pos.getLongitude();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,5 @@ public class OsmNoteQuestType implements QuestType
@Override public AbstractQuestAnswerFragment createForm() { return new NoteDiscussionForm(); }
@Override public int getIcon() { return R.drawable.ic_quest_notes; }
@Override public int getTitle() { return R.string.quest_noteDiscussion_title; }

@Override public int getDefaultDisabledMessage() { return 0; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,6 @@ else if ("footway".equals(tags.get("construction")))
}
return R.string.quest_construction_generic_title;
}

@Override public boolean hasMarkersAtEnds() { return true; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,6 @@ else if(noProperRoad == AddRoadNameForm.IS_LINK)
if (isPedestrian) return R.string.quest_streetName_pedestrian_title;
else return R.string.quest_streetName_title;
}

@Override public boolean hasMarkersAtEnds() { return true; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,6 @@ else if (maxspeed != null)
// see #813: US has different rules for each different state which need to be respected
return Countries.allExcept(new String[]{"US"});
}

@Override public boolean hasMarkersAtEnds() { return true; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,6 @@ private static int findClosestPositionIndexOf(List<LatLon> positions, LatLon lat
{
return R.string.quest_oneway_title;
}

@Override public boolean hasMarkersAtEnds() { return true; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -386,35 +386,39 @@ public void addQuests(Iterable quests, QuestGroup group)
continue;
}

if(first) first = false;
else geoJson.append(",");

LatLon pos = quest.getMarkerLocation();
String questIconName = getActivity().getResources().getResourceEntryName(quest.getType().getIcon());

Integer order = questTypeOrder.get(quest.getType());
if(order == null) order = 0;

geoJson.append("{\"type\":\"Feature\",");
geoJson.append("\"geometry\":{\"type\":\"Point\",\"coordinates\": [");
geoJson.append(pos.getLongitude());
geoJson.append(",");
geoJson.append(pos.getLatitude());
geoJson.append("]},\"properties\": {\"type\":\"point\", \"kind\":\"");
geoJson.append(questIconName);
geoJson.append("\",\"");
geoJson.append(MARKER_QUEST_GROUP);
geoJson.append("\":\"");
geoJson.append(group.name());
geoJson.append("\",\"");
geoJson.append(MARKER_QUEST_ID);
geoJson.append("\":\"");
geoJson.append(quest.getId());
geoJson.append("\",\"");
geoJson.append("order");
geoJson.append("\":\"");
geoJson.append(order);
geoJson.append("\"}}");
LatLon[] positions = quest.getMarkerLocations();

for (LatLon pos : positions)
{
if(first) first = false;
else geoJson.append(",");

geoJson.append("{\"type\":\"Feature\",");
geoJson.append("\"geometry\":{\"type\":\"Point\",\"coordinates\": [");
geoJson.append(pos.getLongitude());
geoJson.append(",");
geoJson.append(pos.getLatitude());
geoJson.append("]},\"properties\": {\"type\":\"point\", \"kind\":\"");
geoJson.append(questIconName);
geoJson.append("\",\"");
geoJson.append(MARKER_QUEST_GROUP);
geoJson.append("\":\"");
geoJson.append(group.name());
geoJson.append("\",\"");
geoJson.append(MARKER_QUEST_ID);
geoJson.append("\":\"");
geoJson.append(quest.getId());
geoJson.append("\",\"");
geoJson.append("order");
geoJson.append("\":\"");
geoJson.append(order);
geoJson.append("\"}}");
}
}
geoJson.append("]}");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package de.westnordost.streetcomplete.util;

import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class ReverseIterator<T> implements Iterator<T>
{
private final ListIterator<T> iterator;

public ReverseIterator(List<T> list) { this.iterator = list.listIterator(list.size()); }
@Override public boolean hasNext() { return iterator.hasPrevious(); }
@Override public T next() { return iterator.previous(); }
@Override public void remove() { iterator.remove(); }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import de.westnordost.osmapi.map.data.BoundingBox;
import de.westnordost.osmapi.map.data.LatLon;
Expand Down Expand Up @@ -215,12 +216,39 @@ public static List<LatLon> centerLineOfPolyline(List<LatLon> positions)
* @throws IllegalArgumentException if positions list is empty
*/
public static LatLon centerPointOfPolyline(List<LatLon> positions)
{
double halfDistance = distance(positions) / 2;
LatLon result = pointOnPolylineFromStart(positions, halfDistance);
if(result == null) result = positions.get(0);
return result;
}

/**
* @return the point the given amount of meters into the polyline
* @params meters the amount of meters
* @throws IllegalArgumentException if positions list is empty
*/
public static LatLon pointOnPolylineFromStart(List<LatLon> positions, double meters)
{
return pointOnPolyline(positions, meters, false);
}

/**
* @return the point the given amount of meters into the polyline, starting from the end
* @params meters the amount of meters
* @throws IllegalArgumentException if positions list is empty
*/
public static LatLon pointOnPolylineFromEnd(List<LatLon> positions, double meters)
{
return pointOnPolyline(positions, meters, true);
}

private static LatLon pointOnPolyline(List<LatLon> positions, double meters, boolean fromEnd)
{
if(positions.isEmpty()) throw new IllegalArgumentException("positions list is empty");

double halfDistance = distance(positions) / 2;
double distance = 0;
Iterator<LatLon> it = positions.iterator();
Iterator<LatLon> it = fromEnd ? new ReverseIterator<>(positions) : positions.iterator();
LatLon p0 = it.next(), p1;
while (it.hasNext())
{
Expand All @@ -230,17 +258,17 @@ public static LatLon centerPointOfPolyline(List<LatLon> positions)
if(segmentDistance > 0)
{
distance += segmentDistance;
if (distance >= halfDistance)
if (distance >= meters)
{
double ratio = (distance - halfDistance) / segmentDistance;
double ratio = (distance - meters) / segmentDistance;
double lat = p1.getLatitude() - ratio * (p1.getLatitude() - p0.getLatitude());
double lon = normalizeLongitude(p1.getLongitude() - ratio * normalizeLongitude(p1.getLongitude() - p0.getLongitude()));
return new OsmLatLon(lat, lon);
}
}
p0 = p1;
}
return positions.get(0);
return null;
}

/**
Expand Down
Loading

0 comments on commit d7ad909

Please sign in to comment.