Laurent GRÉGOIRE
unread,Nov 5, 2013, 6:16:18 AM11/5/13Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to opentripplanner-dev
Hi all,
I made several refactoring on the vectorized isochrone implementation,
with the main target of re-usability of several part of the code in
other contexts. Below a short description for the record and for comments.
1. Creation of a generic SPTWalker "visitor" class.
Caveat: walk over a ShortestPathTree and callback a user-defined
function at evently spaced points (every d0 meters or less) along the
edge geometries. The prototype is the following:
public class SPTWalker {
public static interface SPTVisitor {
public boolean accept(Edge e);
public void visit(Coordinate c, State s0, State s1,
double d0, double d1);
}
public void walk(SPTVisitor visitor, double d0) { ... }
}
This class is used in the isochrone generator to feed the grid sample.
It's up to the client to compute values based on the s0/s1 States and
d0/d1 curvilinear coordinates of the point. Client can filter the edges
to visit.
2. Dissociation of the accumulative sampling mechanism from the isoline
building z-metric.
Caveat: Split the two process which are somehow un-related in two
classes, 1) an AccumulativeGridSampler which is responsible of the
sampling/closing process, 2) the Z-metric concept being retained for the
isoline building class. The prototype:
public class AccumulativeGridSampler<TZ> {
public interface AccumulativeMetric<TZ> {
public TZ cumulateSample(Coordinate C0, Coordinate Cs,
double z, TZ zS);
public TZ closeSample(TZ zUp, TZ zDown, TZ zRight, TZ zLeft);
}
public AccumulativeGridSampler(
ZSampleGrid<TZ> sampleGrid,
AccumulativeMetric<TZ> metric) { ... }
public void addSamplingPoint(Coordinate C0, double z) { ... }
public void close() { ... }
}
This class rely on a ZSampleGrid<TZ> to work on. It also rely for now on
a "double" z value for performance purpose, this assumption could easily
be relaxed later on if needed. We could further refine this if needed by
splitting the accumulative and closing process.
3. Make the isoline builder work on a generic Delaunay triangulation
instead of a rectangular grid.
Caveat: decorrelate the isoline building process from any assumption
coming upstream. Also this make it work on any Delaunay triangulation
(the triangulation does not have to be a Delaunay one anyway), even
irregular one. The interface is loosely defined and allow any kind of
implementation, for exemple with data generated on the fly.
This also simplify the isoline algorithm by working on triangle instead
of squares; the walking step is greatly simplified as with triangle you
do not have to handle any "saddle point" special case, and by keeping an
open Q of edges to visit.
It work on two inputs:
1) a DelaunayTriangulation<TZ>;
2) a Z-metric to perform Z0 plane intersection detection and Z
interpolation.
Making the new isoline builder work on the rectangular sample grid is
algorithmically-straightforward as the Delaunay-triangulation is only a
matter of splitting each rectangle in two triangle :)
The various prototypes are defined as below:
interface DelaunayPoint<TZ> {
public Coordinate getCoordinates();
public TZ getZ();
}
interface DelaunayEdge<TZ> {
public DelaunayPoint<TZ> getA();
public DelaunayPoint<TZ> getB();
public DelaunayEdge<TZ> getEdge1(boolean ccw);
public DelaunayEdge<TZ> getEdge2(boolean ccw);
}
public interface DelaunayTriangulation<TZ> {
public int edgesCount();
public Iterable<? extends DelaunayEdge<TZ>> edges();
}
public interface IsolineBuilder<TZ> {
public interface ZMetric<TZ> {
public int cut(TZ zA, TZ zB, TZ z0);
public double interpolate(TZ zA, TZ zB, TZ z0);
}
public Geometry computeIsoline(TZ z0);
}
public class DelaunayIsolineBuilder<TZ> implements IsolineBuilder<TZ> {
public DelaunayIsolineBuilder(
DelaunayTriangulation<TZ> triangulation,
ZMetric<TZ> zMetric) { ... }
public Geometry computeIsoline(TZ z0) { ... }
}
The purpose of all this is to be able to re-use various vector isochrone
development in other contexts, I'm thinking for example in the batch
analyst where the output could be a vectorized isoline set.
If you have any comments do not hesitate, I will prepare soon a pull
request with this line of development.
HTH,
--Laurent