use of org.openstreetmap.josm.data.osm.Relation in project josm by JOSM.
the class SplitWayCommand method analyseSplit.
static Analysis analyseSplit(Way way, Way wayToKeep, List<Way> newWays) {
Collection<Command> commandList = new ArrayList<>();
Collection<String> nowarnroles = Config.getPref().getList("way.split.roles.nowarn", Arrays.asList("outer", "inner", "forward", "backward", "north", "south", "east", "west"));
// Change the original way
final List<Node> changedWayNodes = wayToKeep.getNodes();
commandList.add(new ChangeNodesCommand(way, changedWayNodes));
for (Way wayToAdd : newWays) {
commandList.add(new AddCommand(way.getDataSet(), wayToAdd));
}
List<RelationAnalysis> relationAnalyses = new ArrayList<>();
EnumSet<WarningType> warnings = EnumSet.noneOf(WarningType.class);
int numberOfRelations = 0;
for (Relation r : OsmPrimitive.getParentRelations(Collections.singleton(way))) {
if (!r.isUsable()) {
continue;
}
numberOfRelations++;
boolean isSimpleCase = true;
Relation c = null;
String type = Optional.ofNullable(r.get("type")).orElse("");
// Known types of ordered relations.
boolean isOrderedRelation = "route".equals(type) || "multipolygon".equals(type) || "boundary".equals(type);
for (int ir = 0; ir < r.getMembersCount(); ir++) {
RelationMember rm = r.getMember(ir);
if (rm.getMember() == way) {
boolean insert = true;
if (relationSpecialTypes.containsKey(type) && "restriction".equals(relationSpecialTypes.get(type))) {
RelationInformation rValue = treatAsRestriction(r, rm, c, newWays, way, changedWayNodes);
if (rValue.warnme)
warnings.add(WarningType.GENERIC);
insert = rValue.insert;
// Value.relation is null or contains a modified copy
c = rValue.relation;
} else if (!isOrderedRelation) {
// Warn the user when relations that are not a route or multipolygon are modified as a result
// of splitting up the way, because we can't tell if this might break anything.
warnings.add(WarningType.GENERIC);
}
if (insert) {
if (c == null) {
c = new Relation(r);
}
if (rm.hasRole() && !nowarnroles.contains(rm.getRole())) {
warnings.add(WarningType.ROLE);
}
// Attempt to determine the direction the ways in the relation are ordered.
Direction direction = Direction.UNKNOWN;
Set<Way> missingWays = new HashSet<>();
if (isOrderedRelation) {
if (way.lastNode() == way.firstNode()) {
// Self-closing way.
direction = Direction.IRRELEVANT;
} else {
// and can even cause the wrong direction to be guessed (with closed loops).
if (ir - 1 >= 0 && r.getMember(ir - 1).isWay()) {
Way w = r.getMember(ir - 1).getWay();
if (w.isIncomplete())
missingWays.add(w);
else {
if (w.lastNode() == way.firstNode() || w.firstNode() == way.firstNode()) {
direction = Direction.FORWARDS;
} else if (w.firstNode() == way.lastNode() || w.lastNode() == way.lastNode()) {
direction = Direction.BACKWARDS;
}
}
}
if (ir + 1 < r.getMembersCount() && r.getMember(ir + 1).isWay()) {
Way w = r.getMember(ir + 1).getWay();
if (w.isIncomplete())
missingWays.add(w);
else {
if (w.lastNode() == way.firstNode() || w.firstNode() == way.firstNode()) {
direction = Direction.BACKWARDS;
} else if (w.firstNode() == way.lastNode() || w.lastNode() == way.lastNode()) {
direction = Direction.FORWARDS;
}
}
}
if (direction == Direction.UNKNOWN && missingWays.isEmpty()) {
// we cannot detect the direction and no way is missing.
// We can safely assume that the direction doesn't matter.
direction = Direction.IRRELEVANT;
}
}
} else {
int k = 1;
while (ir - k >= 0 || ir + k < r.getMembersCount()) {
if (ir - k >= 0 && r.getMember(ir - k).isWay()) {
Way w = r.getMember(ir - k).getWay();
if (w.lastNode() == way.firstNode() || w.firstNode() == way.firstNode()) {
direction = Direction.FORWARDS;
} else if (w.firstNode() == way.lastNode() || w.lastNode() == way.lastNode()) {
direction = Direction.BACKWARDS;
}
break;
}
if (ir + k < r.getMembersCount() && r.getMember(ir + k).isWay()) {
Way w = r.getMember(ir + k).getWay();
if (w.lastNode() == way.firstNode() || w.firstNode() == way.firstNode()) {
direction = Direction.BACKWARDS;
} else if (w.firstNode() == way.lastNode() || w.lastNode() == way.lastNode()) {
direction = Direction.FORWARDS;
}
break;
}
k++;
}
}
if (direction == Direction.UNKNOWN) {
// We don't have enough information to determine the order of the new ways in this relation.
// This may cause relations to be saved with the two new way sections in reverse order.
//
// This often breaks routes.
//
} else {
missingWays = Collections.emptySet();
}
relationAnalyses.add(new RelationAnalysis(c, rm, direction, missingWays));
isSimpleCase = false;
}
}
}
if (c != null && isSimpleCase) {
if (!r.getMembers().equals(c.getMembers())) {
commandList.add(new ChangeMembersCommand(r, new ArrayList<>(c.getMembers())));
}
// see #19885
c.setMembers(null);
}
}
return new Analysis(relationAnalyses, commandList, warnings, numberOfRelations);
}
use of org.openstreetmap.josm.data.osm.Relation in project josm by JOSM.
the class ConflictResolver method buildResolveCommand.
/**
* Builds the resolution command(s) for the resolved conflicts in this ConflictResolver
*
* @return the resolution command
*/
public Command buildResolveCommand() {
List<Command> commands = new ArrayList<>();
if (tagMerger.getModel().getNumResolvedConflicts() > 0) {
commands.add(tagMerger.getModel().buildResolveCommand(conflict));
}
commands.addAll(propertiesMerger.getModel().buildResolveCommand(conflict));
if (my instanceof Way && nodeListMerger.getModel().isFrozen()) {
commands.add(nodeListMerger.getModel().buildResolveCommand(conflict));
} else if (my instanceof Relation && relationMemberMerger.getModel().isFrozen()) {
commands.add(relationMemberMerger.getModel().buildResolveCommand(conflict));
}
if (isResolvedCompletely()) {
commands.add(new VersionConflictResolveCommand(conflict));
commands.add(new ModifiedConflictResolveCommand(conflict));
}
return new SequenceCommand(tr("Conflict Resolution"), commands);
}
use of org.openstreetmap.josm.data.osm.Relation in project josm by JOSM.
the class PropertiesDialog method editMembership.
/**
* This simply fires up an {@link RelationEditor} for the relation shown; everything else
* is the editor's business.
*
* @param row position
*/
private void editMembership(int row) {
Relation relation = (Relation) membershipData.getValueAt(row, 0);
MainApplication.getMap().relationListDialog.selectRelation(relation);
OsmDataLayer layer = MainApplication.getLayerManager().getActiveDataLayer();
if (!layer.isLocked()) {
List<RelationMember> members = ((MemberInfo) membershipData.getValueAt(row, 1)).role.stream().filter(rm -> rm instanceof RelationMember).map(rm -> (RelationMember) rm).collect(Collectors.toList());
RelationEditor.getEditor(layer, relation, members).setVisible(true);
}
}
use of org.openstreetmap.josm.data.osm.Relation in project josm by JOSM.
the class PropertiesDialog method createSearchSetting.
static SearchSetting createSearchSetting(String key, Collection<? extends IPrimitive> sel, boolean sameType) {
String sep = "";
StringBuilder s = new StringBuilder();
Set<String> consideredTokens = new TreeSet<>();
for (IPrimitive p : sel) {
String val = p.get(key);
if (val == null || (!sameType && consideredTokens.contains(val))) {
continue;
}
String t = "";
if (!sameType) {
t = "";
} else if (p instanceof Node) {
t = "type:node ";
} else if (p instanceof Way) {
t = "type:way ";
} else if (p instanceof Relation) {
t = "type:relation ";
}
String token = new StringBuilder(t).append(val).toString();
if (consideredTokens.add(token)) {
s.append(sep).append('(').append(t).append(SearchCompiler.buildSearchStringForTag(key, val)).append(')');
sep = " OR ";
}
}
final SearchSetting ss = new SearchSetting();
ss.text = s.toString();
ss.caseSensitive = true;
return ss;
}
use of org.openstreetmap.josm.data.osm.Relation in project josm by JOSM.
the class GenericRelationEditor method addPrimitivesToRelation.
/**
* Adds primitives to a given relation.
* @param orig The relation to modify
* @param primitivesToAdd The primitives to add as relation members
* @return The resulting command
* @throws IllegalArgumentException if orig is null
*/
public static Command addPrimitivesToRelation(final Relation orig, Collection<? extends OsmPrimitive> primitivesToAdd) {
CheckParameterUtil.ensureParameterNotNull(orig, "orig");
try {
final Collection<TaggingPreset> presets = TaggingPresets.getMatchingPresets(EnumSet.of(TaggingPresetType.forPrimitive(orig)), orig.getKeys(), false);
Relation target = new Relation(orig);
boolean modified = false;
for (OsmPrimitive p : primitivesToAdd) {
if (p instanceof Relation) {
List<Relation> loop = RelationChecker.checkAddMember(target, (Relation) p);
if (!loop.isEmpty() && loop.get(0).equals(loop.get(loop.size() - 1))) {
warnOfCircularReferences(p, loop);
continue;
}
} else if (MemberTableModel.hasMembersReferringTo(target.getMembers(), Collections.singleton(p)) && !confirmAddingPrimitive(p)) {
continue;
}
final Set<String> roles = findSuggestedRoles(presets, p);
target.addMember(new RelationMember(roles.size() == 1 ? roles.iterator().next() : "", p));
modified = true;
}
List<RelationMember> members = new ArrayList<>(target.getMembers());
// see #19885
target.setMembers(null);
return modified ? new ChangeMembersCommand(orig, members) : null;
} catch (AddAbortException ign) {
Logging.trace(ign);
return null;
}
}
Aggregations