use of org.concord.energy3d.model.Tree 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.Tree in project energy3d by concord-consortium.
the class BuildingCost method showItemizedCost.
@SuppressWarnings("serial")
public void showItemizedCost() {
final JDialog dialog = new JDialog(MainFrame.getInstance(), "Itemized Construction Cost", true);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
final JPanel contentPane = new JPanel(new BorderLayout());
dialog.setContentPane(contentPane);
final JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEtchedBorder());
contentPane.add(panel, BorderLayout.CENTER);
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
Foundation foundation = null;
if (selectedPart instanceof Foundation) {
foundation = (Foundation) selectedPart;
}
final String[] header = new String[] { "ID", "Type", "Cost" };
final int m = header.length;
final List<HousePart> parts = Scene.getInstance().getParts();
int n = 0;
int foundationCount = 0;
for (final HousePart p : parts) {
if (p instanceof Foundation) {
foundationCount++;
}
}
for (final HousePart p : parts) {
if ((p instanceof Human) || (foundationCount > 1 && p instanceof Tree)) {
continue;
}
if (p == foundation || p.getTopContainer() == foundation) {
n++;
}
}
final Object[][] column = new Object[n][m];
int i = 0;
for (final HousePart p : parts) {
if ((p instanceof Human) || (foundationCount > 1 && p instanceof Tree)) {
continue;
}
if (p == foundation || p.getTopContainer() == foundation) {
column[i][0] = p.getId();
String partName = p.toString().substring(0, p.toString().indexOf(')') + 1);
final int beg = partName.indexOf("(");
if (beg != -1) {
partName = partName.substring(0, beg);
}
column[i][1] = partName;
column[i][2] = "$" + getPartCost(p);
i++;
}
}
final JTable table = new JTable(column, header);
table.setModel(new DefaultTableModel(column, header) {
@Override
public boolean isCellEditable(final int row, final int col) {
return false;
}
});
panel.add(new JScrollPane(table), BorderLayout.CENTER);
final JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
contentPane.add(buttonPanel, BorderLayout.SOUTH);
final JButton button = new JButton("Close");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
windowLocation.setLocation(dialog.getLocationOnScreen());
dialog.dispose();
}
});
buttonPanel.add(button);
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(final WindowEvent e) {
windowLocation.setLocation(dialog.getLocationOnScreen());
dialog.dispose();
}
});
dialog.pack();
if (windowLocation.x > 0 && windowLocation.y > 0) {
dialog.setLocation(windowLocation);
} else {
dialog.setLocationRelativeTo(MainFrame.getInstance());
}
dialog.setVisible(true);
}
use of org.concord.energy3d.model.Tree in project energy3d by concord-consortium.
the class CspProjectCost method showPieChart.
@Override
void showPieChart() {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
final Foundation selectedFoundation;
if (selectedPart == null || selectedPart instanceof Tree || selectedPart instanceof Human) {
selectedFoundation = null;
} else if (selectedPart instanceof Foundation) {
selectedFoundation = (Foundation) selectedPart;
} else {
selectedFoundation = selectedPart.getTopContainer();
selectedPart.setEditPointsVisible(false);
SceneManager.getInstance().setSelectedPart(selectedFoundation);
}
String details = "";
int count = 0;
for (final HousePart p : Scene.getInstance().getParts()) {
if (p instanceof Foundation) {
final Foundation foundation = (Foundation) p;
if (!foundation.hasSolarReceiver()) {
count++;
if (selectedFoundation == null) {
double receiverSum = 0;
final List<Mirror> mirrors = foundation.getHeliostats();
if (!mirrors.isEmpty()) {
final ArrayList<Foundation> towers = new ArrayList<Foundation>();
for (final Mirror m : mirrors) {
if (m.getReceiver() != null) {
if (!towers.contains(m.getReceiver())) {
towers.add(m.getReceiver());
}
}
}
if (!towers.isEmpty()) {
for (final Foundation tower : towers) {
receiverSum += getPartCost(tower);
}
}
} else {
final List<FresnelReflector> reflectors = foundation.getFresnelReflectors();
if (!reflectors.isEmpty()) {
final ArrayList<Foundation> absorbers = new ArrayList<Foundation>();
for (final FresnelReflector r : reflectors) {
if (r.getReceiver() != null) {
if (!absorbers.contains(r.getReceiver())) {
absorbers.add(r.getReceiver());
}
}
}
if (!absorbers.isEmpty()) {
for (final Foundation absorber : absorbers) {
receiverSum += getPartCost(absorber);
}
}
}
}
details += "$" + (int) (getCostByFoundation(foundation) + receiverSum) + " (" + foundation.getId() + ") | ";
}
}
}
}
if (selectedFoundation == null) {
if (count > 0) {
details = details.substring(0, details.length() - 2);
}
}
double landSum = 0;
double collectorSum = 0;
double receiverSum = 0;
String info;
if (selectedFoundation != null) {
info = "Zone #" + selectedFoundation.getId();
if (selectedFoundation.hasSolarReceiver()) {
receiverSum = getPartCost(selectedFoundation);
} else {
landSum = getPartCost(selectedFoundation);
final List<Mirror> mirrors = selectedFoundation.getHeliostats();
if (!mirrors.isEmpty()) {
final ArrayList<Foundation> towers = new ArrayList<Foundation>();
for (final Mirror m : mirrors) {
if (m.getReceiver() != null) {
if (!towers.contains(m.getReceiver())) {
towers.add(m.getReceiver());
}
}
}
if (!towers.isEmpty()) {
for (final Foundation tower : towers) {
receiverSum += getPartCost(tower);
}
}
} else {
final List<FresnelReflector> reflectors = selectedFoundation.getFresnelReflectors();
if (!reflectors.isEmpty()) {
final ArrayList<Foundation> absorbers = new ArrayList<Foundation>();
for (final FresnelReflector r : reflectors) {
if (r.getReceiver() != null) {
if (!absorbers.contains(r.getReceiver())) {
absorbers.add(r.getReceiver());
}
}
}
if (!absorbers.isEmpty()) {
for (final Foundation absorber : absorbers) {
receiverSum += getPartCost(absorber);
}
}
}
}
}
for (final HousePart p : Scene.getInstance().getParts()) {
if (p.getTopContainer() == selectedFoundation) {
if (p instanceof SolarCollector) {
// assuming that sensor doesn't cost anything
collectorSum += getPartCost(p);
}
}
}
} else {
info = count + " zones";
for (final HousePart p : Scene.getInstance().getParts()) {
if (p instanceof Foundation) {
final Foundation f = (Foundation) p;
if (f.hasSolarReceiver()) {
receiverSum += getPartCost(p);
} else {
landSum += getPartCost(p);
}
} else if (p instanceof SolarCollector) {
collectorSum += getPartCost(p);
}
}
}
double[] data;
String[] legends;
if (Util.isZero(receiverSum)) {
data = new double[] { landSum, collectorSum };
legends = new String[] { "Land (" + Scene.getInstance().getCspCustomPrice().getLifespan() + " years)", "Collectors" };
} else {
data = new double[] { landSum, collectorSum, receiverSum };
legends = new String[] { "Land (" + Scene.getInstance().getCspCustomPrice().getLifespan() + " years)", "Collectors", "Receivers" };
}
// show them in a popup window
final PieChart pie = new PieChart(data, CspProjectCostGraph.colors, 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 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.Tree in project energy3d by concord-consortium.
the class MainPanel method getRotateButton.
public JButton getRotateButton() {
if (rotateButton == null) {
rotateButton = new JButton();
if (Config.isMac()) {
// for some reason, the newer version of Mac draws border for JButton (but not JToggleButton)
rotateButton.setBorderPainted(false);
}
rotateButton.addMouseListener(refreshUponMouseExit);
rotateButton.setIcon(new ImageIcon(getClass().getResource("icons/rotate_cw.png")));
rotateButton.setToolTipText("<html>Rotate in the clockwise direction (change azimuth).<br>Hold down the Ctrl key and press this button for counter-clockwise rotation.<br>Hold down the Shift key while pressing this button to rotate more slowly.<br>If a component is selected, rotate around its center. Otherwise rotate everything around the origin.</html>");
rotateButton.setFocusable(false);
addMouseOverEffect(rotateButton);
rotateButton.addMouseListener(new MouseAdapter() {
private volatile boolean mousePressed = false;
@Override
public void mousePressed(final MouseEvent e) {
energyButton.setSelected(false);
mousePressed = true;
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart == null || selectedPart instanceof Tree || selectedPart instanceof Human) {
int count = 0;
HousePart hp = null;
for (final HousePart x : Scene.getInstance().getParts()) {
if (x instanceof Foundation) {
count++;
hp = x;
}
}
if (count == 1) {
// if there is only one building, automatically select it to ensure that we always rotate around its center
SceneManager.getInstance().setSelectedPart(hp);
SceneManager.getInstance().refresh();
EnergyPanel.getInstance().updateProperties();
}
}
new Thread("Energy3D Continuous Rotation") {
private int count;
private ChangeAzimuthCommand c;
@Override
public void run() {
final HousePart part = SceneManager.getInstance().getSelectedPart();
if (part != null) {
c = new ChangeAzimuthCommand(part);
}
while (mousePressed) {
SceneManager.getTaskManager().update(new Callable<Object>() {
@Override
public Object call() throws Exception {
if (part == null) {
SceneManager.getInstance().rotateAllFoundations(rotationAngle);
} else {
if (part instanceof Foundation) {
SceneManager.getInstance().rotateFoundation(rotationAngle, true);
} else if (part instanceof SolarPanel) {
final SolarPanel solarPanel = (SolarPanel) part;
solarPanel.setRelativeAzimuth(solarPanel.getRelativeAzimuth() + Math.toDegrees(rotationAngle));
solarPanel.draw();
} else if (part instanceof Rack) {
final Rack rack = (Rack) part;
rack.setRelativeAzimuth(rack.getRelativeAzimuth() + Math.toDegrees(rotationAngle));
rack.draw();
} else if (part instanceof Mirror) {
final Mirror mirror = (Mirror) part;
mirror.setRelativeAzimuth(mirror.getRelativeAzimuth() + Math.toDegrees(rotationAngle));
mirror.draw();
}
}
count++;
Scene.getInstance().setEdited(true);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
EnergyPanel.getInstance().updateProperties();
}
});
return null;
}
});
final int partCount = Scene.getInstance().getParts().size();
try {
// give it enough time for the above call to complete (the more parts it has, the more time it needs)
Thread.sleep(200 + partCount * 5);
} catch (final InterruptedException e) {
}
}
// undo only after the thread ends
if (part == null) {
SceneManager.getInstance().getUndoManager().addEdit(new RotateBuildingCommand(null, rotationAngle * count));
} else {
if (part instanceof Foundation) {
SceneManager.getInstance().getUndoManager().addEdit(new RotateBuildingCommand((Foundation) part, rotationAngle * count));
} else if (part instanceof SolarPanel || part instanceof Rack || part instanceof Mirror) {
if (c != null) {
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
}
}
}.start();
}
@Override
public void mouseReleased(final MouseEvent e) {
mousePressed = false;
}
});
}
return rotateButton;
}
use of org.concord.energy3d.model.Tree 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();
}
});
}
Aggregations