use of org.concord.energy3d.model.Roof in project energy3d by concord-consortium.
the class SceneManager method deleteCurrentSelection.
public void deleteCurrentSelection() {
if (selectedPart == null || selectedPart.getLockEdit()) {
return;
}
if (selectedPart instanceof Foundation) {
final Foundation foundation = (Foundation) selectedPart;
if (!foundation.getChildren().isEmpty() && foundation.getSelectedMesh() == null) {
if (JOptionPane.showConfirmDialog(MainFrame.getInstance(), "Deleting the platform also deletes the building on it. Are you sure?", "Confirmation", JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) {
return;
}
}
}
taskManager.update(new Callable<Object>() {
@Override
public Object call() throws Exception {
if (selectedPart != null) {
// sometimes selectedPart can be null after the callable is sent to the task manager
if (selectedPart instanceof Foundation && ((Foundation) selectedPart).getSelectedMesh() != null) {
// a mesh is selected, instead of a part
final Foundation f = (Foundation) selectedPart;
final Mesh m = f.getSelectedMesh();
if (m != null) {
f.deleteMesh(m);
}
} else {
final RemovePartCommand c = new RemovePartCommand(selectedPart);
if (selectedPart instanceof Wall) {
// undo/redo a gable roof
final Roof roof = ((Wall) selectedPart).getRoof();
if (roof != null) {
final List<Map<Integer, List<Wall>>> gableInfo = new ArrayList<Map<Integer, List<Wall>>>();
if (roof.getGableEditPointToWallMap() != null) {
gableInfo.add(roof.getGableEditPointToWallMap());
}
c.setGableInfo(gableInfo);
}
} else if (selectedPart instanceof Foundation) {
// undo/redo all the gable roofs
final List<Roof> roofs = ((Foundation) selectedPart).getRoofs();
if (!roofs.isEmpty()) {
final List<Map<Integer, List<Wall>>> gableInfo = new ArrayList<Map<Integer, List<Wall>>>();
for (final Roof r : roofs) {
if (r.getGableEditPointToWallMap() != null) {
gableInfo.add(r.getGableEditPointToWallMap());
}
}
c.setGableInfo(gableInfo);
}
}
undoManager.addEdit(c);
Scene.getInstance().remove(selectedPart, true);
}
if (selectedPart.getContainer() != null) {
// redraw its container since we are not calling the costly redrawAll any more
selectedPart.getContainer().draw();
}
selectedPart = null;
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MainPanel.getInstance().getEnergyButton().setSelected(false);
}
});
}
return null;
}
});
}
use of org.concord.energy3d.model.Roof in project energy3d by concord-consortium.
the class SceneManager method mousePressed.
private void mousePressed(final MouseState mouseState, final KeyboardState keyboardState) {
refresh = true;
taskManager.update(new Callable<Object>() {
@Override
public Object call() {
if (zoomLock) {
return null;
}
System.out.println("OPERATION: " + operation);
try {
if (operation == Operation.SELECT || operation == Operation.RESIZE || operation == Operation.ROTATE || operation == Operation.DRAW_ROOF_GABLE) {
if (selectedPart == null || selectedPart.isDrawCompleted()) {
final HousePart previousSelectedPart = selectedPart;
final PickedHousePart pickedPart = SelectUtil.selectHousePart(mouseState.getX(), mouseState.getY(), true);
final UserData pick = pickedPart == null ? null : pickedPart.getUserData();
if (pick == null) {
selectedPart = null;
} else {
selectedPart = pick.getHousePart();
}
if (selectedPart != null) {
// }
if (keyboardState.isDown(Key.LMENU) || keyboardState.isDown(Key.RMENU)) {
if (selectedPart instanceof SolarPanel && selectedPart.getContainer() instanceof Rack) {
// special case
selectedPart = selectedPart.getContainer();
}
}
}
System.out.println("Clicked on: " + pick);
if (pick != null && pick.isEditPoint()) {
cameraControl.setLeftMouseButtonEnabled(false);
}
if (operation == Operation.RESIZE) {
for (final HousePart p : Scene.getInstance().getParts()) {
if (p instanceof Foundation) {
if (p != selectedPart) {
((Foundation) p).setResizeHouseMode(false);
}
}
}
if (selectedPart != null) {
if (selectedPart instanceof Foundation) {
final Foundation foundation = (Foundation) selectedPart;
foundation.setResizeHouseMode(true);
} else {
final Foundation foundation = selectedPart.getTopContainer();
if (foundation != null) {
foundation.setResizeHouseMode(true);
setSelectedPart(foundation);
}
}
}
}
if (operation == Operation.SELECT || operation == Operation.ROTATE) {
if (previousSelectedPart instanceof Foundation) {
final Foundation foundation = (Foundation) previousSelectedPart;
foundation.updateAzimuthArrowVisibility(false);
}
if (selectedPart instanceof Foundation) {
final Foundation foundation = (Foundation) selectedPart;
foundation.drawAzimuthArrow();
foundation.pickMesh(mouseState.getX(), mouseState.getY());
}
if (selectedPart != null) {
final Foundation foundationOfSelectedPart = selectedPart instanceof Foundation ? (Foundation) selectedPart : selectedPart.getTopContainer();
if (foundationOfSelectedPart != null) {
foundationOfSelectedPart.setMovePointsVisible(true);
}
}
}
if (operation == Operation.RESIZE && selectedPart != null) {
if (!(selectedPart instanceof Foundation)) {
selectedPart.setEditPointsVisible(false);
selectedPart = selectedPart.getTopContainer();
}
}
if (selectedPart instanceof Window || selectedPart instanceof Tree || (selectedPart instanceof Foundation && pick.getEditPointIndex() != -1)) {
cameraControl.setLeftMouseButtonEnabled(false);
objectMoveStartPoint = pickedPart.getPoint().clone();
collisionLand.setTranslation(0, 0, objectMoveStartPoint.getZ());
final ArrayList<Vector3> points = selectedPart.getPoints();
if (objectMovePoints == null) {
objectMovePoints = new ArrayList<Vector3>();
} else {
objectMovePoints.clear();
}
for (final Vector3 p : points) {
objectMovePoints.add(p.clone());
}
if (selectedPart instanceof Foundation) {
final Foundation f = (Foundation) selectedPart;
if (f.isGroupMaster()) {
final List<Foundation> g = Scene.getInstance().getFoundationGroup(f);
if (!g.isEmpty()) {
if (objectGroupMovePoints == null) {
objectGroupMovePoints = new HashMap<Foundation, ArrayList<Vector3>>();
} else {
objectGroupMovePoints.clear();
}
for (final Foundation a : g) {
final ArrayList<Vector3> b = new ArrayList<Vector3>();
objectGroupMovePoints.put(a, b);
for (final Vector3 p : a.getPoints()) {
b.add(p.clone());
}
}
}
}
}
}
if (previousSelectedPart != null && previousSelectedPart != selectedPart && operation != Operation.RESIZE) {
previousSelectedPart.setEditPointsVisible(false);
previousSelectedPart.setGridsVisible(false);
previousSelectedPart.setLinePatternVisible(false);
final Foundation foundationOfPreviousSelectedPart = previousSelectedPart instanceof Foundation ? (Foundation) previousSelectedPart : previousSelectedPart.getTopContainer();
if (foundationOfPreviousSelectedPart != null) {
if (selectedPart == null) {
foundationOfPreviousSelectedPart.setMovePointsVisible(false);
} else if (foundationOfPreviousSelectedPart != (selectedPart instanceof Foundation ? (Foundation) selectedPart : selectedPart.getTopContainer())) {
foundationOfPreviousSelectedPart.setMovePointsVisible(false);
}
foundationOfPreviousSelectedPart.clearSelectedMesh();
foundationOfPreviousSelectedPart.setResizeHouseMode(false);
}
}
if (selectedPart != null && !PrintController.getInstance().isPrintPreview()) {
selectedPart.setEditPointsVisible(true);
if (pick.isEditPoint() && pick.getEditPointIndex() != -1 || operation == Operation.RESIZE || selectedPart instanceof Window || selectedPart instanceof Tree) {
if (Scene.getInstance().isSnapToGrids()) {
selectedPart.setGridsVisible(true);
} else {
selectedPart.setLinePatternVisible(true);
}
if (selectedPart instanceof Foundation) {
editPartCommand = new EditFoundationCommand((Foundation) selectedPart, !pick.isEditPoint());
} else if (selectedPart instanceof Rack) {
editPartCommand = new EditRackCommand((Rack) selectedPart);
} else if (selectedPart instanceof ParabolicTrough) {
editPartCommand = new EditParabolicTroughCommand((ParabolicTrough) selectedPart);
} else {
editPartCommand = new EditPartCommand(selectedPart);
}
}
}
SelectUtil.nextPickLayer();
if (operation == Operation.DRAW_ROOF_GABLE && selectedPart instanceof Roof) {
System.out.println("deleting roof #" + pick.getEditPointIndex());
final int roofPartIndex = pick.getEditPointIndex();
final Roof roof = (Roof) selectedPart;
roof.setGable(roofPartIndex, true, undoManager);
}
}
} else {
if (selectedPart != null) {
// selected part can be null in modes other than specified in the if clause
selectedPart.addPoint(mouseState.getX(), mouseState.getY());
}
}
} catch (final Throwable t) {
t.printStackTrace();
BugReporter.report(t);
}
return null;
}
});
}
use of org.concord.energy3d.model.Roof in project energy3d by concord-consortium.
the class SolarRadiation method computeToday.
private void computeToday() {
// save current calendar for restoring at the end of this calculation
final Calendar today = (Calendar) Heliodon.getInstance().getCalendar().clone();
hourOfDay = today.get(Calendar.HOUR_OF_DAY);
minuteOfHour = today.get(Calendar.MINUTE);
today.set(Calendar.SECOND, 0);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.HOUR_OF_DAY, 0);
final String city = (String) EnergyPanel.getInstance().getCityComboBox().getSelectedItem();
dailyAirTemperatures = Weather.computeOutsideTemperature(today, city);
final int timeStep = Scene.getInstance().getTimeStep();
final ReadOnlyVector3[] sunLocations = new ReadOnlyVector3[SolarRadiation.MINUTES_OF_DAY / timeStep];
int totalSteps = 0;
for (int minute = 0; minute < SolarRadiation.MINUTES_OF_DAY; minute += timeStep) {
final ReadOnlyVector3 sunLocation = Heliodon.getInstance().computeSunLocation(today).normalizeLocal();
sunLocations[minute / timeStep] = sunLocation;
if (sunLocation.getZ() > 0) {
totalSteps++;
}
today.add(Calendar.MINUTE, timeStep);
}
totalSteps -= 2;
final double dayLength = totalSteps * timeStep / 60.0;
int step = 1;
setupImportedMeshes();
// for (int minute = MINUTES_OF_DAY / 2; minute < MINUTES_OF_DAY / 2 + timeStep; minute += timeStep) { // test for 12 pm for comparison with shadow
for (int minute = 0; minute < MINUTES_OF_DAY; minute += timeStep) {
final ReadOnlyVector3 sunLocation = sunLocations[minute / timeStep];
if (sunLocation.getZ() > 0) {
final ReadOnlyVector3 directionTowardSun = sunLocation.normalize(null);
calculatePeakRadiation(directionTowardSun, dayLength);
for (final HousePart part : Scene.getInstance().getParts()) {
if (part.isDrawCompleted()) {
if (part instanceof Window) {
computeOnMesh(minute, directionTowardSun, part, part.getRadiationMesh(), (Mesh) part.getRadiationCollisionSpatial(), part.getNormal());
} else if (part instanceof Wall) {
if (((Wall) part).getType() == Wall.SOLID_WALL) {
computeOnMesh(minute, directionTowardSun, part, part.getRadiationMesh(), (Mesh) part.getRadiationCollisionSpatial(), part.getNormal());
}
} else if (part instanceof Door || part instanceof Floor) {
computeOnMesh(minute, directionTowardSun, part, part.getRadiationMesh(), (Mesh) part.getRadiationCollisionSpatial(), part.getNormal());
} else if (part instanceof Foundation) {
final Foundation foundation = (Foundation) part;
for (int i = 0; i < 5; i++) {
final Mesh radiationMesh = foundation.getRadiationMesh(i);
final ReadOnlyVector3 normal = i == 0 ? part.getNormal() : ((UserData) radiationMesh.getUserData()).getNormal();
computeOnMesh(minute, directionTowardSun, part, radiationMesh, foundation.getRadiationCollisionSpatial(i), normal);
}
if (!Scene.getInstance().getOnlySolarComponentsInSolarMap()) {
final List<Node> importedNodes = foundation.getImportedNodes();
if (importedNodes != null) {
for (final Node node : importedNodes) {
for (final Spatial s : node.getChildren()) {
final Mesh m = (Mesh) s;
computeOnImportedMesh(minute, directionTowardSun, foundation, m);
}
}
}
}
} else if (part instanceof Roof) {
for (final Spatial roofPart : ((Roof) part).getRoofPartsRoot().getChildren()) {
if (roofPart.getSceneHints().getCullHint() != CullHint.Always) {
final ReadOnlyVector3 faceDirection = (ReadOnlyVector3) roofPart.getUserData();
final Mesh mesh = (Mesh) ((Node) roofPart).getChild(6);
computeOnMesh(minute, directionTowardSun, part, mesh, mesh, faceDirection);
}
}
} else if (part instanceof SolarPanel) {
computeOnSolarPanel(minute, directionTowardSun, (SolarPanel) part);
} else if (part instanceof Rack) {
computeOnRack(minute, directionTowardSun, (Rack) part);
} else if (part instanceof Mirror) {
computeOnMirror(minute, directionTowardSun, (Mirror) part);
} else if (part instanceof FresnelReflector) {
computeOnFresnelReflector(minute, directionTowardSun, (FresnelReflector) part);
} else if (part instanceof ParabolicTrough) {
computeOnParabolicTrough(minute, directionTowardSun, (ParabolicTrough) part);
} else if (part instanceof ParabolicDish) {
computeOnParabolicDish(minute, directionTowardSun, (ParabolicDish) part);
} else if (part instanceof Sensor) {
computeOnSensor(minute, directionTowardSun, (Sensor) part);
}
}
}
computeOnLand(directionTowardSun);
EnergyPanel.getInstance().progress((int) Math.round(100.0 * step / totalSteps));
step++;
}
}
maxValue = Math.round((MINUTES_OF_DAY / timeStep + 1.0) * (1 - 0.01 * Scene.getInstance().getSolarHeatMapColorContrast()));
// If tracking the sun, the heliodon's calendar has been changed. Restore the time now.
resetTrackables();
}
use of org.concord.energy3d.model.Roof in project energy3d by concord-consortium.
the class SolarRadiation method updateTextures.
public void updateTextures() {
EnergyPanel.getInstance().setComputingStartMillis(System.currentTimeMillis());
maxValue = Math.round((MINUTES_OF_DAY / Scene.getInstance().getTimeStep() + 1.0) * (1 - 0.01 * Scene.getInstance().getSolarHeatMapColorContrast()));
applyTexture(SceneManager.getInstance().getSolarLand());
final int totalMeshes = Scene.getInstance().getParts().size() + Scene.getInstance().countMeshes();
int countMesh = 0;
for (final HousePart part : Scene.getInstance().getParts()) {
if (part instanceof SolarCollector) {
applyTexture(part.getRadiationMesh());
} else {
if (!Scene.getInstance().getOnlySolarComponentsInSolarMap()) {
if (part instanceof Wall || part instanceof Door || part instanceof Floor) {
applyTexture(part.getRadiationMesh());
} else if (part instanceof Foundation) {
final Foundation foundation = (Foundation) part;
for (int i = 0; i < 5; i++) {
applyTexture(foundation.getRadiationMesh(i));
}
final List<Node> importedNodes = foundation.getImportedNodes();
if (importedNodes != null) {
for (final Node node : importedNodes) {
for (final Spatial s : node.getChildren()) {
applyTexture((Mesh) s);
EnergyPanel.getInstance().progress((int) Math.round(100.0 * (countMesh++) / totalMeshes));
}
}
}
} else if (part instanceof Roof) {
for (final Spatial roofPart : ((Roof) part).getRoofPartsRoot().getChildren()) {
if (roofPart.getSceneHints().getCullHint() != CullHint.Always) {
final Mesh mesh = (Mesh) ((Node) roofPart).getChild(6);
applyTexture(mesh);
}
}
}
}
}
countMesh++;
}
EnergyPanel.getInstance().progress(0);
}
use of org.concord.energy3d.model.Roof in project energy3d by concord-consortium.
the class SolarRadiation method computeOnMesh.
// Formula from http://en.wikipedia.org/wiki/Air_mass_(solar_energy)#Solar_intensity
private void computeOnMesh(final int minute, final ReadOnlyVector3 directionTowardSun, final HousePart housePart, final Mesh drawMesh, final Mesh collisionMesh, final ReadOnlyVector3 normal) {
if (normal == null) {
// FIXME: normal can be null sometimes, fix it
return;
}
if (Scene.getInstance().getOnlySolarComponentsInSolarMap()) {
return;
}
MeshDataStore data = onMesh.get(drawMesh);
if (data == null) {
data = initMeshTextureData(drawMesh, collisionMesh, normal, !(housePart instanceof Window));
}
/* needed in order to prevent picking collision with neighboring wall at wall edge (seem 0.1 is too small, 0.5 is about right) */
final ReadOnlyVector3 offset = directionTowardSun.multiply(0.5, null);
final double dot = normal.dot(directionTowardSun);
final double directRadiation = dot > 0 ? calculateDirectRadiation(directionTowardSun, normal) : 0;
final double indirectRadiation = calculateDiffuseAndReflectedRadiation(directionTowardSun, normal);
final int timeStep = Scene.getInstance().getTimeStep();
final double solarStep = Scene.getInstance().getSolarStep();
final double annotationScale = Scene.getInstance().getAnnotationScale();
final double scaleFactor = annotationScale * annotationScale / 60 * timeStep;
// a window itself doesn't really absorb solar energy, but it passes the energy into the house to be absorbed
final float absorption = housePart instanceof Window ? 1 : 1 - housePart.getAlbedo();
if (housePart instanceof Roof) {
// for now, only store this for roofs that have different meshes
if (data.solarPotential == null) {
data.solarPotential = new double[MINUTES_OF_DAY / timeStep];
}
if (data.heatLoss == null) {
data.heatLoss = new double[MINUTES_OF_DAY / timeStep];
}
}
for (int col = 0; col < data.cols; col++) {
final double w = col == data.cols - 1 ? data.p2.distance(data.u.multiply(col * solarStep, null).addLocal(data.p0)) : solarStep;
final ReadOnlyVector3 pU = data.u.multiply(col * solarStep + 0.5 * w, null).addLocal(data.p0);
for (int row = 0; row < data.rows; row++) {
if (EnergyPanel.getInstance().isCancelled()) {
throw new CancellationException();
}
if (data.dailySolarIntensity[row][col] == -1) {
continue;
}
final double h = row == data.rows - 1 ? data.p1.distance(data.p0) - row * solarStep : solarStep;
final ReadOnlyVector3 p = data.v.multiply(row * solarStep + 0.5 * h, null).addLocal(pU).add(offset, null);
final Ray3 pickRay = new Ray3(p, directionTowardSun);
final PickResults pickResults = new PrimitivePickResults();
// assuming that indirect (ambient or diffuse) radiation can always reach a grid point
double radiation = indirectRadiation;
final double scaledArea = w * h * scaleFactor;
if (dot > 0) {
for (final Spatial spatial : collidables) {
if (EnergyPanel.getInstance().isCancelled()) {
throw new CancellationException();
}
if (spatial != collisionMesh) {
PickingUtil.findPick(spatial, pickRay, pickResults, false);
if (pickResults.getNumber() != 0) {
if (housePart instanceof Foundation) {
// at this point, we only show radiation heat map on the first floor
final HousePart collidableOwner = collidablesToParts.get(spatial);
if (collidableOwner instanceof Window) {
radiation += directRadiation * ((Window) collidableOwner).getSolarHeatGainCoefficient();
}
}
break;
}
}
}
if (pickResults.getNumber() == 0) {
radiation += directRadiation;
}
}
data.dailySolarIntensity[row][col] += Scene.getInstance().getOnlyAbsorptionInSolarMap() ? absorption * radiation : radiation;
if (data.solarPotential != null) {
data.solarPotential[minute / timeStep] += radiation * scaledArea;
}
if (!(housePart instanceof Foundation)) {
// exclude radiation on foundation
housePart.getSolarPotential()[minute / timeStep] += radiation * scaledArea;
}
}
}
}
Aggregations