use of org.concord.energy3d.model.Floor in project energy3d by concord-consortium.
the class HeatLoad method computeEnergyToday.
public void computeEnergyToday(final Calendar today) {
today.set(Calendar.SECOND, 0);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.HOUR_OF_DAY, 0);
if (EnergyPanel.getInstance().getCityComboBox().getSelectedItem().equals("")) {
return;
}
final int timeStep = Scene.getInstance().getTimeStep();
final double[] outsideTemperatureRange = Weather.computeOutsideTemperature(today, (String) EnergyPanel.getInstance().getCityComboBox().getSelectedItem());
// System.out.println(today.get(Calendar.DAY_OF_YEAR) + ", " + outsideTemperatureRange[0] + ", " + outsideTemperatureRange[1]);
int iMinute = 0;
for (int minute = 0; minute < SolarRadiation.MINUTES_OF_DAY; minute += timeStep) {
iMinute = minute / timeStep;
final double outsideTemperature = Weather.getInstance().getOutsideTemperatureAtMinute(outsideTemperatureRange[1], outsideTemperatureRange[0], minute);
final double groundTemperature = Scene.getInstance().getGround().getTemperatureMinuteOfDay(today.get(Calendar.DAY_OF_YEAR), minute, 0.5 * (outsideTemperatureRange[1] - outsideTemperatureRange[0]));
for (final HousePart part : Scene.getInstance().getParts()) {
if (part instanceof Human || part instanceof Tree || part instanceof Floor || (part instanceof SolarCollector && !(part instanceof Sensor))) {
continue;
}
final double insideTemperature = (part instanceof Foundation ? (Foundation) part : part.getTopContainer()).getThermostat().getTemperature(today.get(Calendar.MONTH), today.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY, minute / 60);
final float absorption = part instanceof Window ? 0 : 1 - part.getAlbedo();
if (part instanceof Roof) {
// need to compute piece by piece for a roof because sun affects outside temperature of roof part
final Roof roof = (Roof) part;
for (final Spatial child : roof.getRoofPartsRoot().getChildren()) {
if (child.getSceneHints().getCullHint() != CullHint.Always) {
final Mesh mesh = (Mesh) ((Node) child).getChild(6);
final double[] solarPotential = SolarRadiation.getInstance().getSolarPotential(mesh);
final double solarHeat = solarPotential != null ? solarPotential[iMinute] * absorption / roof.getVolumetricHeatCapacity() : 0;
final double deltaT = insideTemperature - (outsideTemperature + solarHeat);
if (part.isDrawCompleted()) {
final double uValue = getUValue(part);
if (Util.isZero(uValue)) {
continue;
}
double heatloss = roof.getAreaWithoutOverhang(mesh) * uValue * deltaT / 1000.0 / 60 * timeStep;
// if the lowest outside temperature is high enough, there is no need to turn on the heater hence no heat loss
if (heatloss > 0 && outsideTemperatureRange[0] >= LOWEST_TEMPERATURE_OF_WARM_DAY) {
heatloss = 0;
}
roof.getHeatLoss()[iMinute] += heatloss;
final double[] heatLossArray = SolarRadiation.getInstance().getHeatLoss(mesh);
if (heatLossArray != null) {
heatLossArray[iMinute] += heatloss;
}
}
}
}
} else if (part instanceof Foundation) {
final Foundation foundation = (Foundation) part;
final double deltaT = insideTemperature - groundTemperature;
if (foundation.isDrawCompleted()) {
final double uValue = getUValue(part);
if (Util.isZero(uValue)) {
continue;
}
final Building building = new Building(foundation);
double area;
if (building.isWallComplete()) {
building.calculate();
area = building.getArea();
} else {
area = foundation.getArea();
}
final double heatloss = area * uValue * deltaT / 1000.0 / 60 * timeStep;
// if (iMinute % 4 == 0) System.out.println((int) (iMinute / 4) + "=" + outsideTemperature + ", " + groundTemperature + ", " + deltaT + ", " + heatloss);
foundation.getHeatLoss()[iMinute] += heatloss;
}
} else {
double deltaT = insideTemperature - outsideTemperature;
if (part instanceof Thermal) {
// direct solar heating raises the outside temperature
deltaT -= part.getSolarPotential()[iMinute] * absorption / ((Thermal) part).getVolumetricHeatCapacity();
}
if (part.isDrawCompleted()) {
final double uValue = getUValue(part);
if (Util.isZero(uValue)) {
continue;
}
double heatloss = part.getArea() * uValue * deltaT / 1000.0 / 60 * timeStep;
// if outside is warm enough, there is no need to turn on the heater hence no heat loss
if (heatloss > 0 && outsideTemperatureRange[0] >= LOWEST_TEMPERATURE_OF_WARM_DAY) {
heatloss = 0;
}
part.getHeatLoss()[iMinute] += heatloss;
}
}
}
}
}
use of org.concord.energy3d.model.Floor in project energy3d by concord-consortium.
the class BuildingCost method showPieChart.
@Override
void showPieChart() {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
final Foundation selectedBuilding;
if (selectedPart == null || selectedPart instanceof Tree || selectedPart instanceof Human) {
selectedBuilding = null;
} else if (selectedPart instanceof Foundation) {
selectedBuilding = (Foundation) selectedPart;
} else {
selectedBuilding = selectedPart.getTopContainer();
selectedPart.setEditPointsVisible(false);
SceneManager.getInstance().setSelectedPart(selectedBuilding);
}
String details = "";
int count = 0;
for (final HousePart p : Scene.getInstance().getParts()) {
if (p instanceof Foundation) {
count++;
if (selectedBuilding == null) {
final Foundation foundation = (Foundation) p;
details += "$" + (int) getCostByFoundation(foundation) + " (" + foundation.getId() + ") | ";
}
}
}
if (selectedBuilding == null) {
if (count > 0) {
details = details.substring(0, details.length() - 2);
}
}
double wallSum = 0;
double floorSum = 0;
double windowSum = 0;
double roofSum = 0;
double foundationSum = 0;
double doorSum = 0;
double solarPanelSum = 0;
double treeSum = 0;
String info;
if (selectedBuilding != null) {
info = "Building #" + selectedBuilding.getId();
foundationSum = getPartCost(selectedBuilding);
for (final HousePart p : Scene.getInstance().getParts()) {
if (p.getTopContainer() == selectedBuilding) {
if (p instanceof Wall) {
wallSum += getPartCost(p);
} else if (p instanceof Floor) {
floorSum += getPartCost(p);
} else if (p instanceof Window) {
windowSum += getPartCost(p);
} else if (p instanceof Roof) {
roofSum += getPartCost(p);
} else if (p instanceof Door) {
doorSum += getPartCost(p);
} else if (p instanceof SolarPanel || p instanceof Rack) {
solarPanelSum += getPartCost(p);
}
}
if (count <= 1) {
if (p instanceof Tree && !p.getLockEdit()) {
treeSum += getPartCost(p);
}
}
}
} else {
info = count + " buildings";
for (final HousePart p : Scene.getInstance().getParts()) {
if (p instanceof Wall) {
wallSum += getPartCost(p);
} else if (p instanceof Floor) {
floorSum += getPartCost(p);
} else if (p instanceof Window) {
windowSum += getPartCost(p);
} else if (p instanceof Roof) {
roofSum += getPartCost(p);
} else if (p instanceof Foundation) {
foundationSum += getPartCost(p);
} else if (p instanceof Door) {
doorSum += getPartCost(p);
} else if (p instanceof SolarPanel || p instanceof Rack) {
solarPanelSum += getPartCost(p);
} else if (p instanceof Tree && !p.getLockEdit()) {
treeSum += getPartCost(p);
}
}
}
final double[] data = new double[] { wallSum, windowSum, roofSum, foundationSum, floorSum, doorSum, solarPanelSum, treeSum };
// show them in a popup window
final PieChart pie = new PieChart(data, BuildingCostGraph.colors, BuildingCostGraph.legends, "$", info, count > 1 ? details : null, true);
pie.setBackground(Color.WHITE);
pie.setBorder(BorderFactory.createEtchedBorder());
final JDialog dialog = new JDialog(MainFrame.getInstance(), "Project Costs by Category", true);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.getContentPane().add(pie, BorderLayout.CENTER);
final JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
final JButton buttonItemize = new JButton("Itemize");
buttonItemize.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
showItemizedCost();
}
});
buttonPanel.add(buttonItemize);
final JButton buttonClose = new JButton("Close");
buttonClose.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
dialog.dispose();
}
});
buttonPanel.add(buttonClose);
dialog.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
dialog.pack();
dialog.setLocationRelativeTo(MainFrame.getInstance());
dialog.setVisible(true);
}
use of org.concord.energy3d.model.Floor in project energy3d by concord-consortium.
the class PopupMenuForFloor method getPopupMenu.
static JPopupMenu getPopupMenu(final MouseEvent e) {
if (e.isShiftDown()) {
SceneManager.getTaskManager().update(new Callable<Object>() {
@Override
public Object call() throws Exception {
Scene.getInstance().pasteToPickedLocationOnFloor();
Scene.getInstance().setEdited(true);
return null;
}
});
return null;
}
if (popupMenuForFloor == null) {
final JMenuItem miInfo = new JMenuItem("Floor");
miInfo.setEnabled(false);
miInfo.setOpaque(true);
miInfo.setBackground(Config.isMac() ? Color.BLACK : Color.GRAY);
miInfo.setForeground(Color.WHITE);
final JMenuItem miPaste = new JMenuItem("Paste");
miPaste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, Config.isMac() ? KeyEvent.META_MASK : InputEvent.CTRL_MASK));
miPaste.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
SceneManager.getTaskManager().update(new Callable<Object>() {
@Override
public Object call() throws Exception {
Scene.getInstance().pasteToPickedLocationOnFloor();
Scene.getInstance().setEdited(true);
return null;
}
});
}
});
final JMenuItem miClear = new JMenuItem("Clear");
miClear.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
SceneManager.getTaskManager().update(new Callable<Object>() {
@Override
public Object call() throws Exception {
Scene.getInstance().removeAllChildren(SceneManager.getInstance().getSelectedPart());
Scene.getInstance().setEdited(true);
return null;
}
});
}
});
final JMenu typeMenu = new JMenu("Type");
final ButtonGroup typeGroup = new ButtonGroup();
final JRadioButtonMenuItem rbmiSolid = new JRadioButtonMenuItem("Solid");
rbmiSolid.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Floor) {
final Floor floor = (Floor) selectedPart;
// final ChangeRoofTypeCommand c = new ChangeRoofTypeCommand(roof);
floor.setType(Floor.SOLID);
floor.draw();
SceneManager.getInstance().refresh();
Scene.getInstance().setEdited(true);
// SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
}
});
typeMenu.add(rbmiSolid);
typeGroup.add(rbmiSolid);
final JRadioButtonMenuItem rbmiTransparent = new JRadioButtonMenuItem("Transparent");
rbmiTransparent.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Floor) {
final Floor floor = (Floor) selectedPart;
// final ChangeRoofTypeCommand c = new ChangeRoofTypeCommand(roof);
floor.setType(Floor.TRANSPARENT);
floor.draw();
SceneManager.getInstance().refresh();
Scene.getInstance().setEdited(true);
// SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
}
});
typeMenu.add(rbmiTransparent);
typeGroup.add(rbmiTransparent);
typeMenu.addMenuListener(new MenuListener() {
@Override
public void menuSelected(final MenuEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Floor) {
final Floor floor = (Floor) selectedPart;
switch(floor.getType()) {
case Floor.SOLID:
Util.selectSilently(rbmiSolid, true);
break;
case Floor.TRANSPARENT:
Util.selectSilently(rbmiTransparent, true);
break;
}
}
}
@Override
public void menuDeselected(final MenuEvent e) {
typeMenu.setEnabled(true);
}
@Override
public void menuCanceled(final MenuEvent e) {
typeMenu.setEnabled(true);
}
});
popupMenuForFloor = createPopupMenu(false, false, new Runnable() {
@Override
public void run() {
final HousePart copyBuffer = Scene.getInstance().getCopyBuffer();
miPaste.setEnabled(copyBuffer instanceof SolarPanel || copyBuffer instanceof Rack);
}
});
popupMenuForFloor.add(miPaste);
popupMenuForFloor.add(miClear);
popupMenuForFloor.addSeparator();
popupMenuForFloor.add(typeMenu);
popupMenuForFloor.add(colorAction);
}
return popupMenuForFloor;
}
use of org.concord.energy3d.model.Floor in project energy3d by concord-consortium.
the class EnergyPanel method updateProperties.
// As this method may be called from a non-Event-Queue thread, updating GUI must be done through invokeLater.
public void updateProperties() {
// update part properties
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
final boolean energyViewShown = MainPanel.getInstance().getEnergyButton().isSelected();
final double meterToFoot;
final String lengthUnit;
switch(Scene.getInstance().getUnit()) {
case USCustomaryUnits:
meterToFoot = 3.28084;
lengthUnit = "ft";
break;
default:
meterToFoot = 1;
lengthUnit = "m";
}
final double scale = Scene.getInstance().getAnnotationScale() * meterToFoot;
final TitledBorder partPanelBorder = (TitledBorder) partPanel.getBorder();
if (selectedPart != null) {
final ReadOnlyVector3 v = selectedPart.getAbsPoint(0);
if (selectedPart instanceof Tree) {
final Tree tree = (Tree) selectedPart;
if (tree.isDrawable()) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
partPanelBorder.setTitle("Tree (" + tree.getId() + "): " + tree.getTreeName());
partProperty1Label.setText(" Spread & Height:");
partProperty2Label.setText(" Type:");
partProperty3Label.setText(" Position:");
final double l = v.length();
double a = 90 + Math.toDegrees(Math.asin(-v.getY() / l));
if (v.getX() < 0) {
a = 360 - a;
}
if (Util.isZero(a - 360)) {
a = 0;
}
partProperty1TextField.setText(ONE_DECIMAL.format(tree.getWidth() * scale) + lengthUnit + ", " + ONE_DECIMAL.format(tree.getHeight() * scale) + lengthUnit);
partProperty2TextField.setText(tree.getTreeName() + " (" + (tree.getTreeType() == Tree.PINE ? "Evergreen" : "Deciduous") + ")");
partProperty3TextField.setText("(" + ONE_DECIMAL.format(v.getX() * scale) + ", " + ONE_DECIMAL.format(v.getY() * scale) + ")" + lengthUnit + " or (" + ONE_DECIMAL.format(l * scale) + lengthUnit + ", " + ONE_DECIMAL.format(a) + "\u00B0)");
partProperty1TextField.putClientProperty("tooltip", "The spread and height of the tree");
partProperty2TextField.putClientProperty("tooltip", "The type of the tree");
partProperty3TextField.putClientProperty("tooltip", "The (x, y) or polar coordinates on the land");
}
});
}
} else if (selectedPart instanceof Human) {
final Human human = (Human) selectedPart;
if (human.isDrawable()) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
partPanelBorder.setTitle("Human (" + human.getId() + "): " + human.getHumanName());
partProperty1Label.setText(" X:");
partProperty2Label.setText(" Y:");
partProperty3Label.setText(" Z:");
partProperty1TextField.setText(ONE_DECIMAL.format(v.getX() * scale) + lengthUnit);
partProperty2TextField.setText(ONE_DECIMAL.format(v.getY() * scale) + lengthUnit);
partProperty3TextField.setText(ONE_DECIMAL.format(v.getZ() * scale) + lengthUnit);
partProperty1TextField.putClientProperty("tooltip", "X coordinate");
partProperty2TextField.putClientProperty("tooltip", "Y coordinate");
partProperty3TextField.putClientProperty("tooltip", "Z coordinate");
}
});
}
} else if (selectedPart instanceof SolarPanel) {
final SolarPanel sp = (SolarPanel) selectedPart;
if (sp.isDrawable()) {
final Foundation f = sp.getTopContainer();
if (f != null) {
double a = sp.getRelativeAzimuth() + f.getAzimuth();
if (a >= 360) {
a -= 360;
}
final double az = a;
final boolean flat = (sp.getContainer() instanceof Roof && Util.isZero(sp.getContainer().getHeight())) || (sp.getContainer() instanceof Foundation);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
String title = "Solar Panel (" + sp.getId() + "), " + (sp.getModelName() == null ? "" : "Model: " + sp.getModelName());
final String trackerName = sp.getTrackerName();
if (trackerName != null) {
title += ", Tracker: " + trackerName;
}
partPanelBorder.setTitle(title);
partProperty1Label.setText(" Size & Position:");
partProperty1TextField.setText(TWO_DECIMALS.format(sp.getPanelWidth() * meterToFoot) + "\u00d7" + TWO_DECIMALS.format(sp.getPanelHeight() * meterToFoot) + lengthUnit + ", (" + ONE_DECIMAL.format(v.getX() * scale) + ", " + ONE_DECIMAL.format(v.getY() * scale) + ", " + ONE_DECIMAL.format(v.getZ() * scale) + ")" + lengthUnit);
partProperty1TextField.putClientProperty("tooltip", "The length, width, and center coordinates of the solar panel");
partProperty2Label.setText(" Angles:");
partProperty2TextField.setText(flat ? "tilt: " + ONE_DECIMAL.format(Util.isZero(sp.getTiltAngle()) ? Math.toDegrees(Math.asin(sp.getNormal().getY())) : sp.getTiltAngle()) + "\u00B0, azimuth: " + ONE_DECIMAL.format(az) + "\u00B0" : " --- ");
partProperty2TextField.putClientProperty("tooltip", "The angles of the solar panel");
final String eff = ONE_DECIMAL.format(sp.getCellEfficiency() * 100) + "%";
if (energyViewShown) {
partProperty3Label.setText(" Efficiency & Yield:");
partProperty3TextField.setText(eff + ", " + TWO_DECIMALS.format(sp.getSolarPotentialToday()) + " kWh");
partProperty3TextField.putClientProperty("tooltip", "The solar cell efficiency and daily yield of the solar panel");
} else {
partProperty3Label.setText(" Efficiency:");
partProperty3TextField.setText(eff);
partProperty3TextField.putClientProperty("tooltip", "The solar cell efficiency of the solar panel");
}
}
});
}
}
} else if (selectedPart instanceof Rack) {
final Rack rack = (Rack) selectedPart;
if (rack.isDrawable()) {
final Foundation f = rack.getTopContainer();
if (f != null) {
double a = rack.getRelativeAzimuth() + f.getAzimuth();
if (a >= 360) {
a -= 360;
}
final double az = a;
final int n = rack.isMonolithic() ? rack.getNumberOfSolarPanels() : rack.getChildren().size();
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
String title = "Rack (" + rack.getId() + ")";
final SolarPanel s = rack.getSolarPanel();
if (s.getModelName() != null) {
title += ", Model: " + s.getModelName();
}
final String trackerName = rack.getTrackerName();
if (trackerName != null) {
title += ", Tracker: " + trackerName;
}
partPanelBorder.setTitle(title);
partProperty1Label.setText(" Size & Center:");
partProperty1TextField.setText(TWO_DECIMALS.format(rack.getRackWidth() * meterToFoot) + "\u00d7" + TWO_DECIMALS.format(rack.getRackHeight() * meterToFoot) + lengthUnit + ", (" + ONE_DECIMAL.format(v.getX() * scale) + ", " + ONE_DECIMAL.format(v.getY() * scale) + ", " + ONE_DECIMAL.format(v.getZ() * scale) + ")" + lengthUnit);
partProperty1TextField.putClientProperty("tooltip", "The length, width, and center coordinates of the rack");
partProperty2Label.setText(" Angles:");
partProperty2TextField.setText("tilt: " + ONE_DECIMAL.format(Util.isZero(rack.getTiltAngle()) ? Math.toDegrees(Math.asin(rack.getNormal().getY())) : rack.getTiltAngle()) + "\u00B0, azimuth: " + ONE_DECIMAL.format(az) + "\u00B0");
partProperty2TextField.putClientProperty("tooltip", "The angles of the rack");
partProperty3Label.setText(" Solar Panels:");
final SolarPanel sp = rack.getSolarPanel();
final String eff = ONE_DECIMAL.format(sp.getCellEfficiency() * 100) + "%";
if (energyViewShown) {
partProperty3Label.setText(" Efficiency & Yield:");
partProperty3TextField.setText(eff + ", " + TWO_DECIMALS.format(rack.getSolarPotentialToday()) + " kWh");
partProperty3TextField.putClientProperty("tooltip", "The solar cell efficiency and daily yield of the solar panel array on the rack");
} else {
if (rack.isMonolithic()) {
final int[] rnc = rack.getSolarPanelRowAndColumnNumbers();
partProperty3TextField.setText("" + n + " (" + rnc[0] + "\u00D7" + rnc[1] + "), " + s.getPanelWidth() + "\u00D7" + s.getPanelHeight() + lengthUnit + ", " + eff);
} else {
partProperty3TextField.setText("" + n);
}
partProperty3TextField.putClientProperty("tooltip", "Number and type of solar panels on this rack");
}
}
});
}
}
} else if (selectedPart instanceof Mirror) {
final Mirror m = (Mirror) selectedPart;
if (m.isDrawable()) {
final Foundation f = m.getTopContainer();
if (f != null) {
double a = m.getRelativeAzimuth() + f.getAzimuth();
if (a >= 360) {
a -= 360;
}
final double az = a;
final boolean flat = m.getContainer() instanceof Foundation;
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
partPanelBorder.setTitle("Heliostat (" + m.getId() + ")");
partProperty1Label.setText(" Size & Center:");
partProperty1TextField.setText(TWO_DECIMALS.format(m.getMirrorWidth() * meterToFoot) + "\u00d7" + TWO_DECIMALS.format(m.getMirrorHeight() * meterToFoot) + lengthUnit + ", (" + ONE_DECIMAL.format(v.getX() * scale) + ", " + ONE_DECIMAL.format(v.getY() * scale) + ", " + ONE_DECIMAL.format(v.getZ() * scale) + ")" + lengthUnit);
partProperty1TextField.putClientProperty("tooltip", "The length, width, and center coordinates of the heliostat");
partProperty2Label.setText(" Angles:");
partProperty2TextField.setText(flat ? "tilt: " + ONE_DECIMAL.format(m.getTiltAngle()) + "\u00B0, azimuth: " + ONE_DECIMAL.format(az) + "\u00B0" : " --- ");
partProperty2TextField.putClientProperty("tooltip", "The angles of the heliostat");
final Foundation receiver = m.getReceiver();
final String s = "R=" + ONE_DECIMAL.format(m.getReflectance() * 100) + "%" + (receiver == null ? "" : ", \u03B7=" + ONE_DECIMAL.format(receiver.getSolarReceiverEfficiency() * 100) + "%");
if (energyViewShown) {
partProperty3Label.setText(" Properties & Yield:");
partProperty3TextField.setText(s + ", " + ONE_DECIMAL.format(m.getSolarPotentialToday() * m.getSystemEfficiency()) + " kWh");
partProperty3TextField.putClientProperty("tooltip", "The physical properties and electric yield of this heliostat");
} else {
partProperty3Label.setText(" Properties:");
partProperty3TextField.setText(s);
partProperty3TextField.putClientProperty("tooltip", "The physical properties of this heliostat");
}
}
});
}
}
} else if (selectedPart instanceof ParabolicTrough) {
final ParabolicTrough t = (ParabolicTrough) selectedPart;
if (t.isDrawable()) {
final Foundation f = t.getTopContainer();
if (f != null) {
double a = t.getRelativeAzimuth() + f.getAzimuth();
if (a >= 360) {
a -= 360;
}
final double az = a;
// http://www.powerfromthesun.net/Book/chapter08/chapter08.html
final double focalLength = t.getSemilatusRectum() * 0.5;
final double d = t.getApertureWidth();
final double h = d * d / (16 * focalLength);
final double rimAngle = Math.toDegrees(Math.atan(1.0 / (d / (8 * h) - (2 * h) / d)));
final double b = 4 * h / d;
final double c = Math.sqrt(b * b + 1);
final double s = 0.5 * d * c + 2 * focalLength * Math.log(b + c);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
partPanelBorder.setTitle("Parabolic Trough (" + t.getId() + ")");
partProperty1Label.setText(" Length & Center:");
partProperty1TextField.setText(TWO_DECIMALS.format(t.getTroughLength() * meterToFoot) + lengthUnit + ", module:" + TWO_DECIMALS.format(t.getModuleLength() * meterToFoot) + lengthUnit + ", (" + ONE_DECIMAL.format(v.getX() * scale) + ", " + ONE_DECIMAL.format(v.getY() * scale) + ", " + ONE_DECIMAL.format(v.getZ() * scale) + ")" + lengthUnit + ", azimuth:" + ONE_DECIMAL.format(az) + "\u00B0");
partProperty1TextField.putClientProperty("tooltip", "Assembly length, module length, center coordinates, and azimith of the parabolic trough");
partProperty2Label.setText(" Parabola Shape:");
partProperty2TextField.setText("f=" + ONE_DECIMAL.format(focalLength * meterToFoot) + lengthUnit + ", d=" + ONE_DECIMAL.format(t.getApertureWidth() * meterToFoot) + lengthUnit + ", h=" + ONE_DECIMAL.format(h * meterToFoot) + lengthUnit + ", \u03C6=" + ONE_DECIMAL.format(rimAngle >= 0 ? rimAngle : 180 + rimAngle) + "\u00B0");
partProperty2TextField.putClientProperty("tooltip", "Parameters of the parabolic shape");
final String str = "R=" + ONE_DECIMAL.format(t.getReflectance() * 100) + "%, s=" + ONE_DECIMAL.format(s * t.getTroughLength() * meterToFoot * meterToFoot) + lengthUnit + "\u00B2, a=" + ONE_DECIMAL.format(d * t.getTroughLength() * meterToFoot * meterToFoot) + lengthUnit + "\u00B2, \u03B1=" + ONE_DECIMAL.format(t.getAbsorptance() * 100) + "%";
if (energyViewShown) {
partProperty3Label.setText(" Properties & Yield:");
partProperty3TextField.setText(str + ", " + ONE_DECIMAL.format(t.getSolarPotentialToday() * t.getSystemEfficiency()) + " kWh");
partProperty3TextField.putClientProperty("tooltip", "The properties and yield of this parabolic trough");
} else {
partProperty3Label.setText(" Properties:");
partProperty3TextField.setText(str);
partProperty3TextField.putClientProperty("tooltip", "The properties of this parabolic trough");
}
}
});
}
}
} else if (selectedPart instanceof ParabolicDish) {
final ParabolicDish d = (ParabolicDish) selectedPart;
if (d.isDrawable()) {
final Foundation f = d.getTopContainer();
if (f != null) {
double a = d.getRelativeAzimuth() + f.getAzimuth();
if (a >= 360) {
a -= 360;
}
final double focalLength = d.getFocalLength();
final double rimRadius = d.getRimRadius();
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
partPanelBorder.setTitle("Parabolic Dish (" + d.getId() + ")");
partProperty1Label.setText(" Size & Center:");
partProperty1TextField.setText("Rim radius=" + TWO_DECIMALS.format(rimRadius * meterToFoot) + lengthUnit + ", (" + ONE_DECIMAL.format(v.getX() * scale) + ", " + ONE_DECIMAL.format(v.getY() * scale) + ", " + ONE_DECIMAL.format(v.getZ() * scale) + ")" + lengthUnit);
partProperty1TextField.putClientProperty("tooltip", "Rim radius and center coordinates of the parabolic dish");
partProperty2Label.setText(" Parabola Shape:");
partProperty2TextField.setText("Focal length=" + ONE_DECIMAL.format(focalLength * meterToFoot) + lengthUnit);
partProperty2TextField.putClientProperty("tooltip", "Parameters of the parabolic shape");
final String str = "R=" + ONE_DECIMAL.format(d.getReflectance() * 100) + "%, \u03B1=" + ONE_DECIMAL.format(d.getAbsorptance() * 100) + "%";
if (energyViewShown) {
partProperty3Label.setText(" Properties & Yield:");
partProperty3TextField.setText(str + ", " + ONE_DECIMAL.format(d.getSolarPotentialToday() * d.getSystemEfficiency()) + " kWh");
partProperty3TextField.putClientProperty("tooltip", "The properties and yield of this parabolic dish");
} else {
partProperty3Label.setText(" Properties:");
partProperty3TextField.setText(str);
partProperty3TextField.putClientProperty("tooltip", "The properties of this parabolic dish");
}
}
});
}
}
} else if (selectedPart instanceof FresnelReflector) {
final FresnelReflector r = (FresnelReflector) selectedPart;
if (r.isDrawable()) {
final Foundation f = r.getTopContainer();
if (f != null) {
double a = r.getRelativeAzimuth() + f.getAzimuth();
if (a >= 360) {
a -= 360;
}
final double az = a;
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
partPanelBorder.setTitle("Fresnel Reflector (" + r.getId() + ")");
partProperty1Label.setText(" Center & Azimuth:");
partProperty1TextField.setText("(" + ONE_DECIMAL.format(v.getX() * scale) + ", " + ONE_DECIMAL.format(v.getY() * scale) + ", " + ONE_DECIMAL.format(v.getZ() * scale) + ")" + lengthUnit + ", azimuth:" + ONE_DECIMAL.format(az) + "\u00B0");
partProperty1TextField.putClientProperty("tooltip", "Center coordinates and azimuth of the Fresnel reflector");
partProperty2Label.setText(" Length & Width:");
partProperty2TextField.setText(TWO_DECIMALS.format(r.getLength() * meterToFoot) + lengthUnit + ", module:" + TWO_DECIMALS.format(r.getModuleLength() * meterToFoot) + lengthUnit + ", " + ONE_DECIMAL.format(r.getModuleWidth() * meterToFoot) + lengthUnit);
partProperty2TextField.putClientProperty("tooltip", "Assembly length, module length, and width of the Fresnel reflector");
final Foundation receiver = r.getReceiver();
final String str = "R=" + ONE_DECIMAL.format(r.getReflectance() * 100) + "%, a=" + ONE_DECIMAL.format(r.getModuleWidth() * r.getLength() * meterToFoot * meterToFoot) + lengthUnit + "\u00B2" + (receiver == null ? "" : ", \u03B7=" + ONE_DECIMAL.format(receiver.getSolarReceiverEfficiency() * 100) + "%");
if (energyViewShown) {
partProperty3Label.setText(" Properties & Yield:");
partProperty3TextField.setText(str + ", " + ONE_DECIMAL.format(r.getSolarPotentialToday() * r.getSystemEfficiency()) + " kWh");
partProperty3TextField.putClientProperty("tooltip", "The properties and yield of this Fresnel reflector");
} else {
partProperty3Label.setText(" Properties:");
partProperty3TextField.setText(str);
partProperty3TextField.putClientProperty("tooltip", "The properties of this Fresnel reflector");
}
}
});
}
}
} else if (selectedPart instanceof Sensor) {
final Sensor sensor = (Sensor) selectedPart;
if (sensor.isDrawable()) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
partPanelBorder.setTitle("Sensor (" + sensor.getId() + ")");
partProperty1Label.setText(" Position:");
partProperty2Label.setText(" Thermal:");
partProperty3Label.setText(" Light:");
partProperty1TextField.setText("(" + ONE_DECIMAL.format(v.getX() * scale) + ", " + ONE_DECIMAL.format(v.getY() * scale) + ", " + ONE_DECIMAL.format(v.getZ() * scale) + ")" + lengthUnit);
partProperty2TextField.setText(TWO_DECIMALS.format(-sensor.getTotalHeatLoss() / sensor.getArea()) + " kWh/day/m\u00B2");
partProperty3TextField.setText(TWO_DECIMALS.format(sensor.getSolarPotentialToday() / sensor.getArea()) + " kWh/day/m\u00B2");
partProperty1TextField.putClientProperty("tooltip", "The (x, y, z) coordinates of the sensor");
partProperty2TextField.putClientProperty("tooltip", "The heat flux measured by the sensor");
partProperty3TextField.putClientProperty("tooltip", "The light intensity measured by the sensor");
}
});
}
} else if (selectedPart instanceof Foundation) {
final Foundation foundation = (Foundation) selectedPart;
if (foundation.isDrawable()) {
final Vector3 v1 = foundation.getAbsPoint(1);
final Vector3 v2 = foundation.getAbsPoint(2);
final Vector3 v3 = foundation.getAbsPoint(3);
final double cx = 0.25 * (v.getX() + v1.getX() + v2.getX() + v3.getX());
final double cy = 0.25 * (v.getY() + v1.getY() + v2.getY() + v3.getY());
final double lx = v.distance(v2);
final double ly = v.distance(v1);
final double lz = foundation.getHeight();
final double az = foundation.getAzimuth();
final String landArea;
final FoundationPolygon polygon = foundation.getPolygon();
if (polygon != null && polygon.isVisible()) {
landArea = " (inset:" + ONE_DECIMAL.format(polygon.getArea()) + ")";
} else {
landArea = "";
}
final Mesh selectedMesh;
final Node selectedNode;
final OrientedBoundingBox nodeBox, meshBox;
final List<Node> nodes = foundation.getImportedNodes();
if (nodes != null) {
selectedMesh = foundation.getSelectedMesh();
if (selectedMesh != null) {
selectedNode = selectedMesh.getParent();
nodeBox = Util.getOrientedBoundingBox(selectedNode);
meshBox = Util.getOrientedBoundingBox(selectedMesh);
} else {
selectedNode = null;
nodeBox = null;
meshBox = null;
}
} else {
selectedMesh = null;
selectedNode = null;
nodeBox = null;
meshBox = null;
}
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if (selectedNode != null) {
final double xNodeBox = 2 * nodeBox.getExtent().getX() * scale;
final double yNodeBox = 2 * nodeBox.getExtent().getY() * scale;
final double zNodeBox = 2 * nodeBox.getExtent().getZ() * scale;
final double xMeshBox = 2 * meshBox.getExtent().getX() * scale;
final double yMeshBox = 2 * meshBox.getExtent().getY() * scale;
final double zMeshBox = 2 * meshBox.getExtent().getZ() * scale;
final ReadOnlyVector3 meshBoxCenter = meshBox.getCenter();
final NodeState ns = foundation.getNodeState(selectedNode);
final Vector3 position = ns.getRelativePosition().add(foundation.getAbsCenter(), null);
Vector3 meshNormal = null;
int meshIndex = -1;
if (selectedMesh.getUserData() instanceof UserData) {
final UserData ud = (UserData) selectedMesh.getUserData();
meshIndex = ud.getMeshIndex();
meshNormal = (Vector3) ud.getNormal();
if (!Util.isZero(az)) {
selectedNode.getRotation().applyPost(meshNormal, meshNormal);
}
}
// System.out.println(">>>" + Util.computeFirstNormal(selectedMesh) + ", " + Util.getFirstNormalFromBuffer(selectedMesh));
final String meshBoxString = TWO_DECIMALS.format(xMeshBox) + "\u00d7" + (TWO_DECIMALS.format(yMeshBox)) + "\u00d7" + (TWO_DECIMALS.format(zMeshBox)) + lengthUnit;
final String meshCenterString = "(" + ONE_DECIMAL.format(meshBoxCenter.getX() * scale) + ", " + ONE_DECIMAL.format(meshBoxCenter.getY() * scale) + ", " + ONE_DECIMAL.format(meshBoxCenter.getZ() * scale) + ")" + lengthUnit;
final String meshNormalString = meshNormal != null ? "(" + TWO_DECIMALS.format(meshNormal.getX()) + ", " + TWO_DECIMALS.format(meshNormal.getY()) + ", " + TWO_DECIMALS.format(meshNormal.getZ()) + ")" : "";
partPanelBorder.setTitle("Node #" + foundation.getImportedNodes().indexOf(selectedNode) + " (" + Util.getFileName(ns.getSourceURL().getPath()).replace("%20", " ") + "), Mesh #" + meshIndex + ", Base #" + foundation.getId());
partProperty1Label.setText(" Node:");
partProperty2Label.setText(" Mesh:");
partProperty1TextField.setText(TWO_DECIMALS.format(xNodeBox) + "\u00d7" + (TWO_DECIMALS.format(yNodeBox)) + "\u00d7" + (TWO_DECIMALS.format(zNodeBox)) + lengthUnit + ", (" + TWO_DECIMALS.format(position.getX() * scale) + ", " + TWO_DECIMALS.format(position.getY() * scale) + ")" + lengthUnit);
partProperty2TextField.setText(meshBoxString + ", " + meshCenterString);
partProperty1TextField.putClientProperty("tooltip", "Dimension and location of the bounding box of the selected node<br>File:" + ns.getSourceURL().getFile());
partProperty2TextField.putClientProperty("tooltip", "Dimension and location of the bounding box of the selected mesh");
if (energyViewShown) {
double dailyMeshSolarPotential = 0;
final double[] meshSolarPotential = SolarRadiation.getInstance().getSolarPotential(selectedMesh);
for (final double x : meshSolarPotential) {
dailyMeshSolarPotential += x;
}
partProperty3Label.setText(" Solar:");
partProperty3TextField.setText("\u2191" + meshNormalString + ", " + TWO_DECIMALS.format(dailyMeshSolarPotential) + " kWh");
partProperty3TextField.putClientProperty("tooltip", "Normal vector and solar potential of the selected mesh");
} else {
partProperty3Label.setText(" Normal:");
partProperty3TextField.setText("\u2191" + meshNormalString + ", " + selectedMesh.getMeshData().getVertexCount() + " vertices");
partProperty3TextField.putClientProperty("tooltip", "Normal vector and vertex count of the selected mesh");
}
} else {
partPanelBorder.setTitle("Foundation (" + foundation.getId() + ")");
partProperty1Label.setText(" Size:");
partProperty1TextField.setText(TWO_DECIMALS.format(lx * scale) + "\u00d7" + (TWO_DECIMALS.format(ly * scale)) + "\u00d7" + (TWO_DECIMALS.format(lz * scale)) + lengthUnit + ", Area\u2248" + ONE_DECIMAL.format(lx * ly * scale * scale) + landArea + lengthUnit + "\u00B2");
partProperty1TextField.putClientProperty("tooltip", "The length and width of the foundation");
partProperty2Label.setText(" Position:");
partProperty2TextField.setText("(" + TWO_DECIMALS.format(cx * scale) + ", " + TWO_DECIMALS.format(cy * scale) + ")" + lengthUnit);
partProperty2TextField.putClientProperty("tooltip", "The (x, y) coordinate of the center of the foundation");
partProperty3Label.setText(" Azimuth:");
partProperty3TextField.setText(TWO_DECIMALS.format(az) + "\u00B0");
partProperty3TextField.putClientProperty("tooltip", "The azimuth of the reference edge");
}
}
});
}
} else if (selectedPart instanceof Roof) {
final Roof roof = (Roof) selectedPart;
if (roof.isDrawable()) {
final double area = roof.getArea();
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
partPanelBorder.setTitle("Roof (" + roof.getId() + ")");
partProperty1Label.setText(" Area & Rise:");
partProperty1TextField.setText("Area = " + TWO_DECIMALS.format(area) + lengthUnit + "\u00B2, Rise = " + TWO_DECIMALS.format(roof.getHeight() * scale) + lengthUnit);
partProperty1TextField.putClientProperty("tooltip", "The total area and the rise of the roof<br>(The rise is the highest point of the roof to the top of the walls.)");
partProperty2Label.setText(" Thermal:");
partProperty3Label.setText(" Solar:");
final String rval = ONE_DECIMAL.format(Util.toUsRValue(roof.getUValue()));
final boolean isBuildingProject = Scene.getInstance().getProjectType() == Foundation.TYPE_BUILDING;
final float absorptance = 1 - roof.getAlbedo();
if (energyViewShown) {
partProperty2TextField.setText("R-value = " + rval + ", Gain = " + TWO_DECIMALS.format(-roof.getTotalHeatLoss()) + " kWh");
partProperty2TextField.putClientProperty("tooltip", "The R-value and daily thermal gain of the roof");
if (isBuildingProject) {
partProperty3TextField.setText("Absorptance = " + TWO_DECIMALS.format(absorptance) + ", Absorption = " + TWO_DECIMALS.format(roof.getSolarPotentialToday() * absorptance) + " kWh");
partProperty3TextField.putClientProperty("tooltip", "The absorptance and daily solar heat gain of the roof surface");
} else {
partProperty3TextField.setText("Radiation energy = " + TWO_DECIMALS.format(roof.getSolarPotentialToday()) + " kWh");
partProperty3TextField.putClientProperty("tooltip", "The solar radiation energy onto this roof surface");
}
} else {
partProperty2TextField.setText("R-value = " + rval + " (US system)");
partProperty2TextField.putClientProperty("tooltip", "The R-value of the roof");
partProperty3TextField.setText("Absorptance = " + TWO_DECIMALS.format(absorptance));
partProperty3TextField.putClientProperty("tooltip", "The absorptance of the roof surface");
}
}
});
}
} else if (selectedPart instanceof Window) {
final Window window = (Window) selectedPart;
if (window.isDrawable()) {
final double lx = window.getWindowWidth();
final double ly = window.getWindowHeight();
final Vector3 v1 = window.getAbsPoint(1);
final Vector3 v2 = window.getAbsPoint(2);
final Vector3 v3 = window.getAbsPoint(3);
final double cx = 0.25 * (v.getX() + v1.getX() + v2.getX() + v3.getX());
final double cy = 0.25 * (v.getY() + v1.getY() + v2.getY() + v3.getY());
final double cz = 0.25 * (v.getZ() + v1.getZ() + v2.getZ() + v3.getZ());
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
partPanelBorder.setTitle("Window (" + window.getId() + ")");
partProperty1Label.setText(" Size & Center:");
partProperty1TextField.setText(TWO_DECIMALS.format(lx) + "\u00d7" + (TWO_DECIMALS.format(ly)) + lengthUnit + " \u2248 " + TWO_DECIMALS.format(lx * ly) + lengthUnit + "\u00B2, (" + TWO_DECIMALS.format(cx * scale) + ", " + TWO_DECIMALS.format(cy * scale) + ", " + TWO_DECIMALS.format(cz * scale) + ")" + lengthUnit);
partProperty1TextField.putClientProperty("tooltip", "The width, height, and center of the window");
partProperty2Label.setText(" Thermal:");
partProperty3Label.setText(" Solar:");
final String shgc = TWO_DECIMALS.format(window.getSolarHeatGainCoefficient());
if (energyViewShown) {
partProperty2TextField.setText("U-Value = " + TWO_DECIMALS.format(Util.toUsUValue(window.getUValue())) + ", Gain = " + TWO_DECIMALS.format(-window.getTotalHeatLoss()) + " kWh");
partProperty2TextField.putClientProperty("tooltip", "The U-value and daily thermal gain of the window");
partProperty3TextField.setText("SHGC = " + shgc + ", Gain = " + TWO_DECIMALS.format(window.getSolarPotentialToday() * window.getSolarHeatGainCoefficient()) + " kWh");
partProperty3TextField.putClientProperty("tooltip", "The SHGC value and daily solar gain of the window");
} else {
partProperty2TextField.setText("U-Value = " + TWO_DECIMALS.format(Util.toUsUValue(window.getUValue())) + " (US system)");
partProperty2TextField.putClientProperty("tooltip", "The U-value of the window");
partProperty3TextField.setText("SHGC = " + shgc);
partProperty3TextField.putClientProperty("tooltip", "The solar heat gain coefficient (SHGC) of the window");
}
}
});
}
} else if (selectedPart instanceof Wall) {
final Wall wall = (Wall) selectedPart;
if (wall.isDrawable()) {
final Vector3 v1 = wall.getAbsPoint(1);
final Vector3 v2 = wall.getAbsPoint(2);
final Vector3 v3 = wall.getAbsPoint(3);
final double cx = 0.25 * (v.getX() + v1.getX() + v2.getX() + v3.getX());
final double cy = 0.25 * (v.getY() + v1.getY() + v2.getY() + v3.getY());
final double cz = 0.25 * (v.getZ() + v1.getZ() + v2.getZ() + v3.getZ());
final double lx = v.distance(v2);
final double ly = v.distance(v1);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
partPanelBorder.setTitle("Wall (" + wall.getId() + ")");
partProperty1Label.setText(" Size & Center:");
partProperty1TextField.setText(TWO_DECIMALS.format(lx * scale) + "\u00d7" + (TWO_DECIMALS.format(ly * scale)) + lengthUnit + " \u2248 " + TWO_DECIMALS.format(lx * ly * scale * scale) + lengthUnit + " \u00B2, " + "(" + TWO_DECIMALS.format(cx * scale) + ", " + TWO_DECIMALS.format(cy * scale) + ", " + TWO_DECIMALS.format(cz * scale) + ")" + lengthUnit);
partProperty1TextField.putClientProperty("tooltip", "The width, height, and center of the wall");
partProperty2Label.setText(" Thermal:");
partProperty3Label.setText(" Solar:");
final String rval = ONE_DECIMAL.format(Util.toUsRValue(wall.getUValue()));
final float absorptance = 1 - wall.getAlbedo();
if (energyViewShown) {
partProperty2TextField.setText("R-Value = " + rval + ", Gain = " + TWO_DECIMALS.format(-wall.getTotalHeatLoss()) + " kWh");
partProperty2TextField.putClientProperty("tooltip", "The R-value and daily thermal gain of the wall");
partProperty3TextField.setText("Absorptance = " + TWO_DECIMALS.format(absorptance) + ", Absorption = " + TWO_DECIMALS.format(wall.getSolarPotentialToday() * absorptance) + " kWh");
partProperty3TextField.putClientProperty("tooltip", "The absorptance and daily solar heat gain of the wall surface");
} else {
partProperty2TextField.setText("R-Value = " + rval + " (US system)");
partProperty2TextField.putClientProperty("tooltip", "The R-value of the wall");
partProperty3TextField.setText("Absorptance = " + TWO_DECIMALS.format(absorptance));
partProperty3TextField.putClientProperty("tooltip", "The absorptance of the wall surface");
}
}
});
}
} else if (selectedPart instanceof Door) {
final Door door = (Door) selectedPart;
if (door.isDrawable()) {
final Vector3 v1 = door.getAbsPoint(1);
final Vector3 v2 = door.getAbsPoint(2);
final Vector3 v3 = door.getAbsPoint(3);
final double cx = 0.25 * (v.getX() + v1.getX() + v2.getX() + v3.getX());
final double cy = 0.25 * (v.getY() + v1.getY() + v2.getY() + v3.getY());
final double cz = 0.25 * (v.getZ() + v1.getZ() + v2.getZ() + v3.getZ());
final double lx = v.distance(v2);
final double ly = v.distance(v1);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
partPanelBorder.setTitle("Door (" + door.getId() + ")");
partProperty1Label.setText(" Size & Center:");
partProperty1TextField.setText(TWO_DECIMALS.format(lx * scale) + "\u00d7" + (TWO_DECIMALS.format(ly * scale)) + lengthUnit + " \u2248 " + TWO_DECIMALS.format(lx * ly * scale * scale) + lengthUnit + "\u00B2, (" + TWO_DECIMALS.format(cx * scale) + ", " + TWO_DECIMALS.format(cy * scale) + ", " + TWO_DECIMALS.format(cz * scale) + ")" + lengthUnit);
partProperty1TextField.putClientProperty("tooltip", "The width, height, and center of the door");
partProperty2Label.setText(" Thermal:");
partProperty3Label.setText(" Solar:");
final String uval = TWO_DECIMALS.format(Util.toUsUValue(door.getUValue()));
final float absorptance = 1 - door.getAlbedo();
if (energyViewShown) {
partProperty2TextField.setText("U-Value = " + uval + ", Gain = " + TWO_DECIMALS.format(-door.getTotalHeatLoss()) + " kWh");
partProperty2TextField.putClientProperty("tooltip", "The R-value and daily thermal gain of the door");
partProperty3TextField.setText("Absorptance = " + TWO_DECIMALS.format(absorptance) + ", Absorption = " + TWO_DECIMALS.format(door.getSolarPotentialToday() * absorptance) + " kWh");
partProperty3TextField.putClientProperty("tooltip", "The absorptance and daily solar heat gain of the door surface");
} else {
partProperty2TextField.setText("U-Value = " + uval + " (US system)");
partProperty2TextField.putClientProperty("tooltip", "The U-value of the door");
partProperty3TextField.setText("Absorptance = " + TWO_DECIMALS.format(absorptance));
partProperty3TextField.putClientProperty("tooltip", "The absorptance of the door surface");
}
}
});
}
} else if (selectedPart instanceof Floor) {
final Floor floor = (Floor) selectedPart;
if (floor.isDrawable()) {
final double cx, cy;
final double cz = v.getZ();
if (floor.getPoints().size() > 1) {
final Vector3 v1 = floor.getAbsPoint(1);
final Vector3 v2 = floor.getAbsPoint(2);
final Vector3 v3 = floor.getAbsPoint(3);
cx = 0.25 * (v.getX() + v1.getX() + v2.getX() + v3.getX());
cy = 0.25 * (v.getY() + v1.getY() + v2.getY() + v3.getY());
} else {
cx = v.getX();
cy = v.getY();
}
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
partPanelBorder.setTitle("Floor (" + floor.getId() + ")");
partProperty1Label.setText(" Area & Center");
partProperty1TextField.setText(ONE_DECIMAL.format(floor.getArea()) + lengthUnit + "\u00B2, (" + ONE_DECIMAL.format(cx * scale) + ", " + ONE_DECIMAL.format(cy * scale) + ", " + ONE_DECIMAL.format(cz * scale) + ")" + lengthUnit);
partProperty1TextField.putClientProperty("tooltip", "The area and center of the floor");
partProperty2Label.setText(" Thermal:");
partProperty2TextField.setText("N.A.");
partProperty2TextField.putClientProperty("tooltip", "Not applicable to thermal analysis");
partProperty3Label.setText(" Solar:");
partProperty3TextField.setText("N.A.");
partProperty3TextField.putClientProperty("tooltip", "Not applicable to solar analysis");
}
});
}
}
} else {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
final int numberOfSolarPanels = Scene.getInstance().countSolarPanels();
if (numberOfSolarPanels > 0) {
partPanelBorder.setTitle("Solar Panels");
partProperty1Label.setText(" Total Number:");
partProperty1TextField.setText("" + numberOfSolarPanels);
partProperty1TextField.putClientProperty("tooltip", "Total number of solar panels");
partProperty2Label.setText(" Total Cost:");
partProperty2TextField.setText("$" + TWO_DECIMALS.format(PvProjectCost.getInstance().getTotalCost()));
partProperty2TextField.putClientProperty("tooltip", "Total cost of solar panels");
partProperty3Label.setText(" -");
partProperty3TextField.setText("");
partProperty3TextField.putClientProperty("tooltip", null);
} else {
final int numberOfHeliostats = Scene.getInstance().countParts(Mirror.class);
if (numberOfHeliostats > 0) {
partPanelBorder.setTitle("Heliostats");
partProperty1Label.setText(" Total Number:");
partProperty1TextField.setText("" + numberOfHeliostats);
partProperty1TextField.putClientProperty("tooltip", "Total number of heliostats");
partProperty2Label.setText(" Total Cost:");
partProperty2TextField.setText("$" + TWO_DECIMALS.format(CspProjectCost.getInstance().getTotalCost()));
partProperty2TextField.putClientProperty("tooltip", "Total cost of heliostats");
partProperty3Label.setText(" -");
partProperty3TextField.setText("");
partProperty3TextField.putClientProperty("tooltip", null);
} else {
final int numberOfParabolicTroughs = Scene.getInstance().countParts(ParabolicTrough.class);
if (numberOfParabolicTroughs > 0) {
partPanelBorder.setTitle("Parabolic Troughs");
partProperty1Label.setText(" Total Number:");
partProperty1TextField.setText("" + numberOfParabolicTroughs);
partProperty1TextField.putClientProperty("tooltip", "Total number of parabolic troughs");
partProperty2Label.setText(" Total Cost:");
partProperty2TextField.setText("$" + TWO_DECIMALS.format(CspProjectCost.getInstance().getTotalCost()));
partProperty2TextField.putClientProperty("tooltip", "Total cost of parabolic troughs");
partProperty3Label.setText(" -");
partProperty3TextField.setText("");
partProperty3TextField.putClientProperty("tooltip", null);
} else {
final int numberOfParabolicDishes = Scene.getInstance().countParts(ParabolicDish.class);
if (numberOfParabolicDishes > 0) {
partPanelBorder.setTitle("Parabolic Dishes");
partProperty1Label.setText(" Total Number:");
partProperty1TextField.setText("" + numberOfParabolicDishes);
partProperty1TextField.putClientProperty("tooltip", "Total number of parabolic dishes");
partProperty2Label.setText(" Total Cost:");
partProperty2TextField.setText("$" + TWO_DECIMALS.format(CspProjectCost.getInstance().getTotalCost()));
partProperty2TextField.putClientProperty("tooltip", "Total cost of parabolic dishes");
partProperty3Label.setText(" -");
partProperty3TextField.setText("");
partProperty3TextField.putClientProperty("tooltip", null);
} else {
final int numberOfFresnelReflectors = Scene.getInstance().countParts(FresnelReflector.class);
if (numberOfFresnelReflectors > 0) {
partPanelBorder.setTitle("Fresnel Reflectors");
partProperty1Label.setText(" Total Number:");
partProperty1TextField.setText("" + numberOfFresnelReflectors);
partProperty1TextField.putClientProperty("tooltip", "Total number of Fresnel reflectors");
partProperty2Label.setText(" Total Cost:");
partProperty2TextField.setText("$" + TWO_DECIMALS.format(CspProjectCost.getInstance().getTotalCost()));
partProperty2TextField.putClientProperty("tooltip", "Total cost of Fresnel reflectors");
partProperty3Label.setText(" -");
partProperty3TextField.setText("");
partProperty3TextField.putClientProperty("tooltip", null);
} else {
final int numberOfNodes = Scene.getInstance().countNodes();
if (numberOfNodes > 0) {
partPanelBorder.setTitle("Structures");
partProperty1Label.setText(" Total Nodes:");
partProperty1TextField.setText("" + numberOfNodes);
partProperty1TextField.putClientProperty("tooltip", "Total number of structure nodes");
partProperty2Label.setText(" Total Meshes:");
partProperty2TextField.setText("" + Scene.getInstance().countMeshes());
partProperty2TextField.putClientProperty("tooltip", "Total number of structure meshes");
partProperty3Label.setText(" -");
partProperty3TextField.setText("");
partProperty3TextField.putClientProperty("tooltip", null);
} else {
partPanelBorder.setTitle(" -");
partProperty1Label.setText(" -");
partProperty1TextField.setText("");
partProperty1TextField.putClientProperty("tooltip", null);
partProperty2Label.setText(" -");
partProperty2TextField.setText("");
partProperty2TextField.putClientProperty("tooltip", null);
partProperty3Label.setText(" -");
partProperty3TextField.setText("");
partProperty3TextField.putClientProperty("tooltip", null);
}
}
}
}
}
}
}
});
}
partPanel.repaint();
// update building properties
final Foundation selectedFoundation;
if (selectedPart == null) {
selectedFoundation = null;
} else if (selectedPart instanceof Foundation) {
selectedFoundation = (Foundation) selectedPart;
} else {
selectedFoundation = selectedPart.getTopContainer();
}
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if (selectedFoundation != null) {
switch(selectedFoundation.getProjectType()) {
case Foundation.TYPE_BUILDING:
dataPanel.remove(instructionPanel);
dataPanel.remove(pvProjectPanel);
dataPanel.remove(cspProjectPanel);
dataPanel.add(buildingPanel, 2);
final Calendar c = Heliodon.getInstance().getCalendar();
final int temp = selectedFoundation.getThermostat().getTemperature(c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY, c.get(Calendar.HOUR_OF_DAY));
switch(Scene.getInstance().getUnit()) {
case InternationalSystemOfUnits:
thermostatTemperatureField.setText(temp + " \u00B0C");
break;
case USCustomaryUnits:
thermostatTemperatureField.setText(Math.round(32.0 + 9.0 * temp / 5.0) + " \u00B0F");
break;
}
thermostatPanel.add(adjustThermostatButton, BorderLayout.EAST);
String s2 = selectedFoundation.toString();
s2 = s2.substring(0, s2.indexOf(')') + 1);
final int i1 = s2.indexOf('(');
final int i2 = s2.indexOf(')');
((TitledBorder) buildingPanel.getBorder()).setTitle("Building #" + s2.substring(i1 + 1, i2));
buildingInfoPanel.update(selectedFoundation);
break;
case Foundation.TYPE_PV_PROJECT:
dataPanel.remove(instructionPanel);
dataPanel.remove(buildingPanel);
dataPanel.remove(cspProjectPanel);
dataPanel.add(pvProjectPanel, 2);
pvProjectInfoPanel.update(selectedFoundation);
break;
case Foundation.TYPE_CSP_PROJECT:
dataPanel.remove(instructionPanel);
dataPanel.remove(buildingPanel);
dataPanel.remove(pvProjectPanel);
dataPanel.add(cspProjectPanel, 2);
cspProjectInfoPanel.update(selectedFoundation);
break;
case -1:
dataPanel.remove(instructionPanel);
dataPanel.remove(buildingPanel);
dataPanel.remove(pvProjectPanel);
dataPanel.remove(cspProjectPanel);
break;
}
} else {
dataPanel.remove(buildingPanel);
dataPanel.remove(pvProjectPanel);
dataPanel.remove(cspProjectPanel);
dataPanel.add(instructionPanel, 2);
for (int i = 0; i < instructionSheets.length; i++) {
final String contentType = Scene.getInstance().getInstructionSheetTextType(i);
instructionSheets[i].setContentType(contentType == null ? "text/plain" : contentType);
if (!instructionSheets[i].getText().equals(Scene.getInstance().getInstructionSheetText(i))) {
instructionSheets[i].setText(Scene.getInstance().getInstructionSheetText(i));
}
}
}
dataPanel.validate();
dataPanel.repaint();
}
});
}
use of org.concord.energy3d.model.Floor in project energy3d by concord-consortium.
the class BuildingCostGraph method calculateCost.
private void calculateCost() {
int countBuildings = 0;
for (final HousePart p : Scene.getInstance().getParts()) {
if (p instanceof Foundation) {
countBuildings++;
}
}
wallSum = 0;
floorSum = 0;
windowSum = 0;
roofSum = 0;
doorSum = 0;
solarPanelSum = 0;
treeSum = 0;
foundationSum = BuildingCost.getPartCost(foundation);
for (final HousePart p : Scene.getInstance().getParts()) {
if (p.getTopContainer() == foundation) {
if (p instanceof Wall) {
wallSum += BuildingCost.getPartCost(p);
} else if (p instanceof Floor) {
floorSum += BuildingCost.getPartCost(p);
} else if (p instanceof Window) {
windowSum += BuildingCost.getPartCost(p);
} else if (p instanceof Roof) {
roofSum += BuildingCost.getPartCost(p);
} else if (p instanceof Door) {
doorSum += BuildingCost.getPartCost(p);
} else if (p instanceof SolarPanel) {
solarPanelSum += BuildingCost.getPartCost(p);
} else if (p instanceof Rack) {
solarPanelSum += BuildingCost.getPartCost(p);
}
}
if (countBuildings <= 1) {
if (p instanceof Tree && !p.getLockEdit()) {
treeSum += BuildingCost.getPartCost(p);
}
}
}
totalCost = wallSum + windowSum + roofSum + doorSum + solarPanelSum + treeSum + foundationSum + floorSum;
}
Aggregations