@Override public BoundingBox getBounds() { // If there are no charges, return an empty box. if (charges.size() <= 0) return new BoundingBox(0, 0, 0, 0, 0, 0); if (cachedBounds == null) { // Start with the box of the first charge. Charge c = charges.get(0); double ext = Math.abs(c.w); double corr = 1.0 + (0.1 / hardness); // see note cachedBounds = new BoundingBox( new Vec3(c.x - ext, c.y - ext, c.z - ext).times(corr), new Vec3(c.x + ext, c.y + ext, c.z + ext).times(corr)); // A note on "corr": // As blobs are blobby, we can't use their weight/radius // directly. This would result in unwanted cut-off's. To // correct this, we extend the bounding box of a charge "a // bit". That "bit" can be smaller if the charge is harder. // Iteratively add the remaining charges. for (int i = 1; i < charges.size(); i++) { c = charges.get(i); ext = Math.abs(c.w); corr = 1.0 + (0.1 / hardness); cachedBounds.extend( new BoundingBox( new Vec3(c.x - ext, c.y - ext, c.z - ext).times(corr), new Vec3(c.x + ext, c.y + ext, c.z + ext).times(corr))); } } return cachedBounds; }
@Override public double getFieldValue(double x, double y, double z, double size, double time) { double sum = 0.0, dist; double val; for (Charge c : charges) { // Distances. dist = c.getDist(x, y, z); // Calculate value. // Actually, this is: weight * (1.0 / distance) // But we start with the square of it to save the // calculation of a square root. val = (c.w * c.w) / dist; // This charge's "hardness". val = Math.pow(val, hardness); // Revert divisions by zero and the like. if (Double.isNaN(val) || Double.isInfinite(val)) continue; // Additive or subtractive charge. if (c.w >= 0.0) sum += val; else sum -= val; } return sum; }