package org.osm2world.core.target;
import static org.osm2world.core.target.statistics.StatisticsTarget.Stat.PRIMITIVE_COUNT;
import static org.osm2world.core.util.FaultTolerantIterationUtil.iterate;
import java.util.Iterator;
import org.osm2world.core.map_data.data.MapData;
import org.osm2world.core.map_data.data.MapElement;
import org.osm2world.core.map_elevation.data.GroundState;
import org.osm2world.core.target.common.RenderableToPrimitiveTarget;
import org.osm2world.core.target.statistics.StatisticsTarget;
import org.osm2world.core.util.FaultTolerantIterationUtil.Operation;
import org.osm2world.core.world.data.WorldObject;
public final class TargetUtil {
private TargetUtil() {}
/**
* render all world objects to a target instance
* that are compatible with that target type
*/
public static <R extends Renderable> void renderWorldObjects(
final Target<R> target, final MapData mapData,
final boolean renderUnderground) {
for (MapElement mapElement : mapData.getMapElements()) {
for (WorldObject r : mapElement.getRepresentations()) {
if (renderUnderground || r.getGroundState() != GroundState.BELOW) {
try {
renderObject(target, r);
} catch (Exception e) {
System.err.println("ignored exception:");
//TODO proper logging
e.printStackTrace();
System.err.println("this exception occurred for the following input:\n"
+ mapElement);
}
}
}
}
}
/**
* render all world objects to a target instances
* that are compatible with that target type.
* World objects are added to a target until the number of primitives
* reaches the primitive threshold, then the next target is retrieved
* from the iterator.
*/
public static <R extends RenderableToPrimitiveTarget> void renderWorldObjects(
final Iterator<? extends Target<R>> targetIterator,
final MapData mapData, final int primitiveThresholdPerTarget) {
final StatisticsTarget primitiveCounter = new StatisticsTarget();
iterate(mapData.getMapElements(), new Operation<MapElement>() {
Target<R> currentTarget = targetIterator.next();
@Override public void perform(MapElement e) {
for (WorldObject r : e.getRepresentations()) {
renderObject(primitiveCounter, r);
renderObject(currentTarget, r);
if (primitiveCounter.getGlobalCount(PRIMITIVE_COUNT)
>= primitiveThresholdPerTarget) {
currentTarget = targetIterator.next();
primitiveCounter.clear();
}
}
}
});
}
/**
* renders any object to a target instance
* if it is a renderable compatible with that target type.
* Also sends {@link Target#beginObject(WorldObject)} calls.
*/
public static final <R extends Renderable> void renderObject(
final Target<R> target, Object object) {
Class<R> renderableType = target.getRenderableType();
if (renderableType.isInstance(object)) {
if (object instanceof WorldObject) {
target.beginObject((WorldObject)object);
} else {
target.beginObject(null);
}
target.render(renderableType.cast(object));
} else if (object instanceof RenderableToAllTargets) {
if (object instanceof WorldObject) {
target.beginObject((WorldObject)object);
} else {
target.beginObject(null);
}
((RenderableToAllTargets)object).renderTo(target);
}
}
}