use of de.fhpotsdam.unfolding.marker.Marker in project constellation by constellation-app.
the class AbstractPathsLayer method update.
@Override
public PImage update() {
if (graph == null) {
return null;
}
final Set<Marker> onScreenMarkers;
final List<Tuple<GraphElement, GraphElement>> paths = new ArrayList<>();
try (final ReadableGraph readableGraph = graph.getReadableGraph()) {
// update on screen markers, collecting the ids of the vertices involved in valid paths along the way
final ScreenPosition topLeft = map.getScreenPosition(map.getTopLeftBorder());
final ScreenPosition bottomRight = map.getScreenPosition(map.getBottomRightBorder());
onScreenMarkers = renderer.getMarkerCache().keys().stream().filter(marker -> {
final ScreenPosition markerPosition = map.getScreenPosition(marker.getLocation());
final boolean onScreen = markerPosition != null && markerPosition.x > topLeft.x && markerPosition.y > topLeft.y && markerPosition.x < bottomRight.x && markerPosition.y < bottomRight.y;
if (drawPathsToOffscreenMarkers() || onScreen) {
final Set<GraphElement> elementsAtMarker = renderer.getMarkerCache().get(marker);
if (elementsAtMarker != null) {
elementsAtMarker.forEach(element -> paths.addAll(getPathsForElement(readableGraph, element)));
}
}
return onScreen;
}).collect(Collectors.toSet());
onScreenMarkerCount = onScreenMarkers.size();
}
if (onScreenMarkers.isEmpty()) {
return null;
}
final Map<GraphElement, Marker> elementToMarkerCache = new HashMap<>();
renderer.getMarkerCache().keys().forEach(marker -> renderer.getMarkerCache().get(marker).forEach(element -> elementToMarkerCache.put(element, marker)));
// set up a color palette
final int[] palette = Arrays.asList(ConstellationColor.createLinearPalette(N_COLORS, SRC_COLOR, DST_COLOR)).stream().mapToInt(c -> MarkerUtilities.color(c)).toArray();
final int width = renderer.width - 5;
final int height = renderer.height - 5;
final PGraphics pathsImage = renderer.createGraphics(width, height, PConstants.JAVA2D);
pathsImage.beginDraw();
// deduplicate paths, storing duplicate counts
int maxWeight = 1;
final Map<Tuple<GraphElement, GraphElement>, Integer> dedupedPaths = new HashMap<>();
for (final Tuple<GraphElement, GraphElement> path : paths) {
if (dedupedPaths.containsKey(path)) {
final int weight = dedupedPaths.get(path) + 1;
if (weight > maxWeight) {
maxWeight = weight;
}
dedupedPaths.put(path, weight);
} else {
dedupedPaths.put(path, 1);
}
}
// draw weighted paths
final int maxWeightFinal = maxWeight;
dedupedPaths.forEach((path, weight) -> {
final Marker sourceMarker = elementToMarkerCache.get(path.getFirst());
final Marker destinationMarker = elementToMarkerCache.get(path.getSecond());
final boolean validPath = (drawPathsToOffscreenMarkers() && (onScreenMarkers.contains(sourceMarker) || onScreenMarkers.contains(destinationMarker))) || (onScreenMarkers.contains(sourceMarker) && onScreenMarkers.contains(destinationMarker));
if (validPath) {
final Location sourceLocation = sourceMarker != null ? sourceMarker.getLocation() : null;
final Location destinationLocation = destinationMarker != null ? destinationMarker.getLocation() : null;
if (sourceLocation != null && destinationLocation != null) {
final ScreenPosition sourcePosition = map.getScreenPosition(sourceLocation);
final ScreenPosition destinationPosition = map.getScreenPosition(destinationLocation);
final float lineWidth = Math.max(maxWeightFinal > MAX_LINE_WIDTH ? (MAX_LINE_WIDTH * (weight / (float) maxWeightFinal)) + 1 : weight + 1, 2);
pathsImage.strokeWeight(lineWidth);
pathsImage.pushMatrix();
pathsImage.translate(sourcePosition.x, sourcePosition.y);
pathsImage.rotate(PApplet.atan2((destinationPosition.y - sourcePosition.y), (destinationPosition.x - sourcePosition.x)));
final float translatedDestiniationPosition = (float) Math.hypot(destinationPosition.x - sourcePosition.x, destinationPosition.y - sourcePosition.y);
drawColoredLine(pathsImage, translatedDestiniationPosition, lineWidth, palette);
pathsImage.popMatrix();
}
}
});
pathsImage.endDraw();
return pathsImage;
}
use of de.fhpotsdam.unfolding.marker.Marker in project constellation by constellation-app.
the class ThiessenPolygonsLayer method update.
@Override
public PImage update() {
// update on screen markers
final ScreenPosition topLeft = map.getScreenPosition(map.getTopLeftBorder());
final ScreenPosition bottomRight = map.getScreenPosition(map.getBottomRightBorder());
final List<Marker> onScreenMarkers = map.getMarkers().stream().filter(marker -> {
final ScreenPosition markerPosition = map.getScreenPosition(marker.getLocation());
return !marker.isHidden() && markerPosition != null && markerPosition.x > topLeft.x && markerPosition.y > topLeft.y && markerPosition.x < bottomRight.x && markerPosition.y < bottomRight.y;
}).collect(Collectors.toList());
onScreenMarkerCount = onScreenMarkers.size();
if (onScreenMarkers.isEmpty()) {
return null;
}
// map markers to screen positions
final Map<Marker, ScreenPosition> positionMap = onScreenMarkers.stream().collect(Collectors.toMap(marker -> marker, marker -> map.getScreenPosition(marker.getLocation()), (marker1, marker2) -> marker1));
// map markers to colors
final ConstellationColor[] palette = ConstellationColor.createPalette(onScreenMarkerCount);
final Map<Marker, Integer> paletteMap = new HashMap<>();
onScreenMarkers.forEach(marker -> paletteMap.put(marker, MarkerUtilities.color(palette[onScreenMarkers.indexOf(marker)])));
final int width = renderer.width - 5;
final int height = renderer.height - 5;
final PImage voronoiImage = renderer.createImage(width, height, PConstants.ARGB);
voronoiImage.loadPixels();
for (int pixelIndex = 0; pixelIndex < voronoiImage.pixels.length; pixelIndex++) {
// find the closest marker to this pixel
final ScreenPosition pixelPosition = pixelPosition(pixelIndex, width, height);
Marker closestMarker = null;
for (final Marker marker : onScreenMarkers) {
if (closestMarker == null) {
closestMarker = marker;
} else {
final ScreenPosition markerPosition = positionMap.get(marker);
final ScreenPosition closestMarkerPosition = positionMap.get(closestMarker);
if (markerPosition != null && closestMarkerPosition != null && euclidianDistance((int) pixelPosition.x, (int) pixelPosition.y, (int) markerPosition.x, (int) markerPosition.y) < euclidianDistance((int) pixelPosition.x, (int) pixelPosition.y, (int) closestMarkerPosition.x, (int) closestMarkerPosition.y)) {
closestMarker = marker;
}
}
}
// color this pixel based on its closest marker
if (closestMarker != null && paletteMap.get(closestMarker) != null) {
voronoiImage.pixels[pixelIndex] = paletteMap.get(closestMarker);
}
}
voronoiImage.updatePixels();
return voronoiImage;
}
use of de.fhpotsdam.unfolding.marker.Marker in project constellation by constellation-app.
the class ConstellationClusterMarker method getDistanceTo.
@Override
public double getDistanceTo(final Location location) {
double minDistance = Double.MAX_VALUE;
for (final Marker marker : markers) {
final double dist = marker.getDistanceTo(location);
minDistance = dist < minDistance ? dist : minDistance;
}
return minDistance;
}
use of de.fhpotsdam.unfolding.marker.Marker in project constellation by constellation-app.
the class ConstellationMultiMarker method getDistanceTo.
@Override
public double getDistanceTo(final Location location) {
double minDistance = Double.MAX_VALUE;
for (final Marker marker : markers) {
final double dist = marker.getDistanceTo(location);
minDistance = dist < minDistance ? dist : minDistance;
}
return minDistance;
}
use of de.fhpotsdam.unfolding.marker.Marker in project constellation by constellation-app.
the class AbstractHeatmapLayer method update.
@Override
public PImage update() {
// update on screen markers
final ScreenPosition topLeft = map.getScreenPosition(map.getTopLeftBorder());
final ScreenPosition bottomRight = map.getScreenPosition(map.getBottomRightBorder());
final List<Marker> onScreenMarkers = renderer.getMarkerCache().keys().stream().filter(marker -> {
final ScreenPosition markerPosition = map.getScreenPosition(marker.getLocation());
return !marker.isHidden() && markerPosition != null && markerPosition.x > topLeft.x && markerPosition.y > topLeft.y && markerPosition.x < bottomRight.x && markerPosition.y < bottomRight.y;
}).collect(Collectors.toList());
onScreenMarkerCount = onScreenMarkers.size();
if (onScreenMarkers.isEmpty()) {
return null;
}
// create point image from markers
final int width = renderer.width - 5;
final int height = renderer.height - 5;
final float[] pointImage = new float[width * height];
onScreenMarkers.forEach(marker -> {
final ConstellationAbstractMarker constellationMarker = (ConstellationAbstractMarker) marker;
final ScreenPosition markerPosition = map.getScreenPosition(constellationMarker.getLocation());
final float markerWeight = getWeight(constellationMarker);
if (markerPosition != null) {
pointImage[(int) markerPosition.y * width + (int) markerPosition.x] = markerWeight;
}
});
// generate gaussian blur around points
final float[] gaussImage = new float[width * height];
GaussianBlur.gaussianBlurBox(pointImage, gaussImage, width, height, RADIUS, PASSES, GaussianBlur.BoxBlurType.FASTEST);
final PImage heatmapImage = renderer.createImage(width, height, PConstants.ARGB);
heatmapImage.loadPixels();
GaussianBlur.colorise(gaussImage, heatmapImage.pixels, THRESHOLD, SEVERITY);
heatmapImage.updatePixels();
return heatmapImage;
}
Aggregations