/* * Copyright (c) 2014 tabletoptool.com team. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * rptools.com team - initial implementation * tabletoptool.com team - further development */ package com.t3.client.walker; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import com.t3.model.CellPoint; import com.t3.model.Path; import com.t3.model.Zone; public abstract class AbstractZoneWalker implements ZoneWalker { protected List<PartialPath> partialPaths = new ArrayList<PartialPath>(); protected final Zone zone; public AbstractZoneWalker(Zone zone) { this.zone = zone; } public Zone getZone() { return zone; } @Override public CellPoint getLastPoint() { if (partialPaths.isEmpty()) { return null; } PartialPath lastPath = partialPaths.get(partialPaths.size() - 1); return lastPath.end; } @Override public void setWaypoints(CellPoint... points) { partialPaths.clear(); addWaypoints(points); } @Override public void addWaypoints(CellPoint... points) { CellPoint previous = partialPaths.size() > 0 ? partialPaths.get(partialPaths.size() - 1).end : null; for (CellPoint current : points) { if (previous != null) { partialPaths.add(new PartialPath(previous, current, calculatePath(previous, current))); } previous = current; } } @Override public CellPoint replaceLastWaypoint(CellPoint point) { if (partialPaths.isEmpty()) return null; PartialPath oldPartial = partialPaths.remove(partialPaths.size() - 1); // short circuit exit if the point hasn't changed. // if (oldPartial.end.equals(point)) // return null; partialPaths.add(new PartialPath(oldPartial.start, point, calculatePath(oldPartial.start, point))); return oldPartial.end; } @Override public Path<CellPoint> getPath() { Path<CellPoint> path = new Path<CellPoint>(); PartialPath last = null; for (PartialPath partial : partialPaths) { if (partial.path != null && partial.path.size() > 1) { path.addAllPathCells(partial.path.subList(0, partial.path.size() - 1)); } last = partial; } if (last != null) { path.addPathCell(last.end); } for (CellPoint cp : path.getCellPath()) { if (isWaypoint(cp)) { path.addWayPoint(cp); } } return path; } @Override public boolean isWaypoint(CellPoint point) { if (point == null) return false; PartialPath last = null; for (PartialPath partial : partialPaths) { if (partial.start.equals(point)) return true; last = partial; } if (last != null && last.end != null && last.end.equals(point)) return true; return false; } /** * @see com.t3.client.walker.ZoneWalker#removeWaypoint(com.t3.model.CellPoint) */ @Override public boolean removeWaypoint(CellPoint aPoint) { if (aPoint == null || partialPaths == null || partialPaths.isEmpty()) return false; // Find the partial path with the given end point ListIterator<PartialPath> i = partialPaths.listIterator(); while (i.hasNext()) { PartialPath path = i.next(); if (path.end.equals(aPoint)) { // If this is the last partial path then done, otherwise // combine this path and the next and replace them with a combined path if (!i.hasNext()) return false; i.remove(); PartialPath path2 = i.next(); i.set(new PartialPath(path.start, path2.end, calculatePath(path.start, path2.end))); return true; } // endif } // endwhile return false; } /** * @see com.t3.client.walker.ZoneWalker#toggleWaypoint(com.t3.model.CellPoint) */ @Override public boolean toggleWaypoint(CellPoint aPoint) { if (removeWaypoint(aPoint)) return true; addWaypoints(aPoint); return true; } /** * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder s = new StringBuilder("Path: "); for (PartialPath path : partialPaths) { s.append("\n "); s.append(path.toString()); } // endfor return s.toString(); } protected abstract List<CellPoint> calculatePath(CellPoint start, CellPoint end); protected static class PartialPath { final CellPoint start; final CellPoint end; final List<CellPoint> path; public PartialPath(CellPoint start, CellPoint end, List<CellPoint> path) { this.start = start; this.end = end; this.path = path; } /** * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder s = new StringBuilder("PartialPath(["); s.append(start.x); s.append(","); s.append(start.y); s.append("], ["); s.append(end.x); s.append(","); s.append(end.y); s.append("]"); return s.toString(); } } }