use of gaiasky.scenegraph.particle.IParticleRecord in project gaiasky by langurmonkey.
the class SerializedDataProvider method loadData.
public List<IParticleRecord> loadData(InputStream is, double factor) {
try {
ObjectInputStream ois = new ObjectInputStream(is);
@SuppressWarnings("unchecked") List<IParticleRecord> // cast is needed.
l = (List<IParticleRecord>) ois.readObject();
ois.close();
// Convert to Array, reconstruct index
int n = l.size();
initLists(n);
list.addAll(l);
return list;
} catch (Exception e) {
logger.error(e);
}
return null;
}
use of gaiasky.scenegraph.particle.IParticleRecord in project gaiasky by langurmonkey.
the class OctreeGeneratorMag method generateOctree.
@Override
public OctreeNode generateOctree(List<IParticleRecord> catalog) {
root = IOctreeGenerator.startGeneration(catalog, params);
// Holds all octree nodes indexed by id
LongMap<OctreeNode> idMap = new LongMap<>();
idMap.put(root.pageId, root);
// Contains the list of objects for each node
Map<OctreeNode, List<IParticleRecord>> objMap = new HashMap<>();
int catalogSize = catalog.size();
int catalogIndex = 0;
for (int level = 0; level <= 19; level++) {
logger.info("Generating level " + level + " (" + (catalog.size() - catalogIndex) + " stars left)");
while (catalogIndex < catalogSize) {
// Add stars to nodes until we reach max part
IParticleRecord sb = catalog.get(catalogIndex++);
double x = sb.x();
double y = sb.y();
double z = sb.z();
Long nodeId = getPositionOctantId(x, y, z, level);
if (!idMap.containsKey(nodeId)) {
// Create octant and parents if necessary
OctreeNode octant = createOctant(nodeId, x, y, z, level);
// Add to idMap
idMap.put(octant.pageId, octant);
}
// Add star to node
OctreeNode octant = idMap.get(nodeId);
int addedNum = addStarToNode(sb, octant, objMap);
if (addedNum >= params.maxPart) {
// On to next level!
break;
}
}
if (catalogIndex >= catalog.size()) {
// All stars added -> FINISHED
break;
}
}
if (params.postprocess) {
logger.info("Post-processing octree: childcount=" + params.childCount + ", parentcount=" + params.parentCount);
long mergedNodes = 0;
long mergedObjects = 0;
// We merge low-count nodes (<= childcount) with parents, if parents' count is <= parentcount
Object[] nodes = objMap.keySet().toArray();
// Sort by descending depth
Arrays.sort(nodes, (node1, node2) -> {
OctreeNode n1 = (OctreeNode) node1;
OctreeNode n2 = (OctreeNode) node2;
return Integer.compare(n2.depth, n1.depth);
});
int n = objMap.size();
for (int i = n - 1; i >= 0; i--) {
OctreeNode current = (OctreeNode) nodes[i];
if (current.numChildren() == 0 && current.parent != null && objMap.containsKey(current) && objMap.containsKey(current.parent)) {
List<IParticleRecord> childArr = objMap.get(current);
List<IParticleRecord> parentArr = objMap.get(current.parent);
if (childArr.size() <= params.childCount && parentArr.size() <= params.parentCount) {
// Merge children nodes with parent nodes, remove children
parentArr.addAll(childArr);
objMap.remove(current);
current.remove();
mergedNodes++;
mergedObjects += childArr.size();
}
}
}
logger.info("POSTPROCESS STATS:");
logger.info(" Merged nodes: " + mergedNodes);
logger.info(" Merged objects: " + mergedObjects);
}
// Tree is ready, create star groups
Set<OctreeNode> nodes = objMap.keySet();
for (OctreeNode node : nodes) {
List<IParticleRecord> list = objMap.get(node);
StarGroup sg = new StarGroup();
sg.setData(list, false);
node.add(sg);
sg.octant = node;
sg.octantId = node.pageId;
}
root.updateCounts();
return root;
}
use of gaiasky.scenegraph.particle.IParticleRecord in project gaiasky by langurmonkey.
the class OctreeGeneratorPart method treatLevel.
/**
* Generate the octree on a per-level basis to have a uniform density in all
* the nodes of the same level. Breadth-first.
*
* @param inputLists List of star beans per octant
* @param level The depth
* @param octantsPerLevel Octants of each level
* @param percentage Percentage
*/
private void treatLevel(Map<OctreeNode, List<IParticleRecord>> inputLists, int level, Array<OctreeNode>[] octantsPerLevel, float percentage) {
logger.info("Generating level " + level);
Array<OctreeNode> levelOctants = octantsPerLevel[level];
octantsPerLevel[level + 1] = new Array<>(false, levelOctants.size * 8);
/**
* CREATE OCTANTS FOR LEVEL+1 *
*/
Iterator<OctreeNode> it = levelOctants.iterator();
while (it.hasNext()) {
OctreeNode octant = it.next();
List<IParticleRecord> list = inputLists.get(octant);
if (list.size() == 0) {
// Empty node, remove
it.remove();
octant.remove();
} else {
boolean leaf = aggregation.sample(list, octant, percentage);
if (!leaf) {
// Generate 8 children per each level octant
double hsx = octant.size.x / 4d;
double hsy = octant.size.y / 4d;
double hsz = octant.size.z / 4d;
/**
* CREATE SUB-OCTANTS *
*/
// Front - top - left
octantsPerLevel[level + 1].add(new OctreeNode(octant.centre.x - hsx, octant.centre.y + hsy, octant.centre.z - hsz, hsx, hsy, hsz, octant.depth + 1, octant, 0));
// Front - top - right
octantsPerLevel[level + 1].add(new OctreeNode(octant.centre.x + hsx, octant.centre.y + hsy, octant.centre.z - hsz, hsx, hsy, hsz, octant.depth + 1, octant, 1));
// Front - bottom - left
octantsPerLevel[level + 1].add(new OctreeNode(octant.centre.x - hsx, octant.centre.y - hsy, octant.centre.z - hsz, hsx, hsy, hsz, octant.depth + 1, octant, 2));
// Front - bottom - right
octantsPerLevel[level + 1].add(new OctreeNode(octant.centre.x + hsx, octant.centre.y - hsy, octant.centre.z - hsz, hsx, hsy, hsz, octant.depth + 1, octant, 3));
// Back - top - left
octantsPerLevel[level + 1].add(new OctreeNode(octant.centre.x - hsx, octant.centre.y + hsy, octant.centre.z + hsz, hsx, hsy, hsz, octant.depth + 1, octant, 4));
// Back - top - right
octantsPerLevel[level + 1].add(new OctreeNode(octant.centre.x + hsx, octant.centre.y + hsy, octant.centre.z + hsz, hsx, hsy, hsz, octant.depth + 1, octant, 5));
// Back - bottom - left
octantsPerLevel[level + 1].add(new OctreeNode(octant.centre.x - hsx, octant.centre.y - hsy, octant.centre.z + hsz, hsx, hsy, hsz, octant.depth + 1, octant, 6));
// Back - bottom - right
octantsPerLevel[level + 1].add(new OctreeNode(octant.centre.x + hsx, octant.centre.y - hsy, octant.centre.z + hsz, hsx, hsy, hsz, octant.depth + 1, octant, 7));
}
}
}
/**
* IF WE HAVE OCTANTS IN THE NEXT LEVEL, INTERSECT *
*/
if (octantsPerLevel[level + 1].size != 0) {
/**
* INTERSECT CATALOG WITH OCTANTS, COMPUTE PERCENTAGE *
*/
int maxSublevelObjs = 0;
double maxSublevelMag = Double.MAX_VALUE;
double minSublevelMag = 0;
Map<OctreeNode, List<IParticleRecord>> lists = new HashMap<>();
for (OctreeNode octant : octantsPerLevel[level + 1]) {
List<IParticleRecord> list = intersect(inputLists.get(octant.parent), octant);
lists.put(octant, list);
if (list.size() > maxSublevelObjs) {
maxSublevelObjs = list.size();
}
// Adapt levels by magnitude
for (IParticleRecord pb : list) {
IParticleRecord sb = pb;
if (sb.absmag() < maxSublevelMag) {
maxSublevelMag = sb.absmag();
}
if (sb.absmag() > minSublevelMag) {
minSublevelMag = sb.absmag();
}
}
}
float sublevelPercentage = MathUtils.clamp((float) aggregation.getMaxPart() / (float) maxSublevelObjs, 0f, 1f);
/**
* GO ONE MORE LEVEL DOWN *
*/
treatLevel(lists, level + 1, octantsPerLevel, sublevelPercentage);
}
}
use of gaiasky.scenegraph.particle.IParticleRecord in project gaiasky by langurmonkey.
the class UncertaintiesProvider method loadData.
@Override
public List<IParticleRecord> loadData(String file, double factor) {
FileHandle f = Settings.settings.data.dataFileHandle(file);
@SuppressWarnings("unchecked") List<IParticleRecord> pointData = loadData(f.read(), factor);
if (pointData != null)
logger.info(I18n.txt("notif.nodeloader", pointData.size(), file));
return pointData;
}
use of gaiasky.scenegraph.particle.IParticleRecord in project gaiasky by langurmonkey.
the class IOctreeGenerator method startGeneration.
/**
* Computes the maximum axis-aligned bounding box containing
* all the particles in the catalog, and returns it as the root
* octree node.
* @param catalog The incoming catalog
* @param params The octree generation parameters
* @return The root octree node
*/
static OctreeNode startGeneration(List<IParticleRecord> catalog, OctreeGeneratorParams params) {
logger.info("Starting generation of octree");
// Minimum and maximum positions
Vector3d min = new Vector3d(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE);
Vector3d max = new Vector3d(-Double.MAX_VALUE, -Double.MAX_VALUE, -Double.MAX_VALUE);
Iterator<IParticleRecord> it = catalog.iterator();
while (it.hasNext()) {
IParticleRecord particle = it.next();
// Min
if (particle.x() < min.x) {
min.x = particle.x();
}
if (particle.y() < min.y) {
min.y = particle.y();
}
if (particle.z() < min.z) {
min.z = particle.z();
}
// Max
if (particle.x() > max.x) {
max.x = particle.x();
}
if (particle.y() > max.y) {
max.y = particle.y();
}
if (particle.z() > max.z) {
max.z = particle.z();
}
}
BoundingBoxd box = new BoundingBoxd(min, max);
double halfSize = Math.max(Math.max(box.getDepth(), box.getHeight()), box.getWidth()) / 2d;
OctreeNode root = new OctreeNode(0, box.getCenterX(), box.getCenterY(), box.getCenterZ(), halfSize, halfSize, halfSize, 0);
return root;
}
Aggregations