Search in sources :

Example 41 with ParabolicTrough

use of org.concord.energy3d.model.ParabolicTrough in project energy3d by concord-consortium.

the class SetShapeForParabolicTroughsOnFoundationCommand method undo.

@Override
public void undo() throws CannotUndoException {
    super.undo();
    final int n = troughs.size();
    newLengths = new double[n];
    newApertureWidths = new double[n];
    newSemilatusRecta = new double[n];
    newModuleLengths = new double[n];
    for (int i = 0; i < n; i++) {
        final ParabolicTrough t = troughs.get(i);
        newLengths[i] = t.getTroughLength();
        newApertureWidths[i] = t.getApertureWidth();
        newSemilatusRecta[i] = t.getSemilatusRectum();
        newModuleLengths[i] = t.getModuleLength();
        t.setTroughLength(oldLengths[i]);
        t.setApertureWidth(oldApertureWidths[i]);
        t.setSemilatusRectum(oldSemilatusRecta[i]);
        t.setModuleLength(oldModuleLengths[i]);
        t.draw();
    }
    SceneManager.getInstance().refresh();
}
Also used : ParabolicTrough(org.concord.energy3d.model.ParabolicTrough)

Example 42 with ParabolicTrough

use of org.concord.energy3d.model.ParabolicTrough in project energy3d by concord-consortium.

the class SetPartSizeCommand method redo.

@Override
public void redo() throws CannotRedoException {
    super.redo();
    if (part instanceof Mirror) {
        final Mirror m = (Mirror) part;
        m.setMirrorWidth(newWidth);
        m.setMirrorHeight(newHeight);
    } else if (part instanceof ParabolicTrough) {
        final ParabolicTrough t = (ParabolicTrough) part;
        t.setApertureWidth(newWidth);
        t.setTroughLength(newHeight);
        t.setModuleLength(newModuleLength);
    } else if (part instanceof ParabolicDish) {
        final ParabolicDish d = (ParabolicDish) part;
        d.setRimRadius(newWidth);
    } else if (part instanceof FresnelReflector) {
        final FresnelReflector t = (FresnelReflector) part;
        t.setModuleWidth(newWidth);
        t.setLength(newHeight);
        t.setModuleLength(newModuleLength);
    } else if (part instanceof Rack) {
        final Rack r = (Rack) part;
        r.setRackWidth(newWidth);
        r.setRackHeight(newHeight);
    } else if (part instanceof Window) {
        final Window w = (Window) part;
        w.setWindowWidth(newWidth);
        w.setWindowHeight(newHeight);
        w.getContainer().draw();
    } else if (part instanceof Door) {
        final Door d = (Door) part;
        d.setDoorWidth(newWidth);
        d.setDoorHeight(newHeight);
        d.getContainer().draw();
    }
    part.draw();
    SceneManager.getInstance().refresh();
}
Also used : ParabolicDish(org.concord.energy3d.model.ParabolicDish) Window(org.concord.energy3d.model.Window) Rack(org.concord.energy3d.model.Rack) ParabolicTrough(org.concord.energy3d.model.ParabolicTrough) FresnelReflector(org.concord.energy3d.model.FresnelReflector) Mirror(org.concord.energy3d.model.Mirror) Door(org.concord.energy3d.model.Door)

Example 43 with ParabolicTrough

use of org.concord.energy3d.model.ParabolicTrough in project energy3d by concord-consortium.

the class CspProjectInfoPanel method update.

void update(final Foundation foundation) {
    final List<ParabolicTrough> troughs = foundation.getParabolicTroughs();
    if (!troughs.isEmpty()) {
        countBar.setValue(troughs.size());
        int totalModules = 0;
        for (final ParabolicTrough t : troughs) {
            totalModules += t.getNumberOfModules();
        }
        moduleCountBar.setValue(totalModules);
        countPanel.setBorder(EnergyPanel.createTitledBorder("Number of parabolic troughs", true));
        double cost = 0;
        double reflectingArea = 0;
        double troughArea = 0;
        final CspCustomPrice price = Scene.getInstance().getCspCustomPrice();
        for (final ParabolicTrough t : troughs) {
            troughArea = t.getTroughLength() * t.getApertureWidth();
            cost += price.getParabolicTroughUnitPrice() * troughArea;
            reflectingArea += troughArea;
        }
        cost += foundation.getArea() * price.getLandUnitPrice() * price.getLifespan();
        costBar.setValue(Math.round(cost));
        final CspDesignSpecs specs = Scene.getInstance().getCspDesignSpecs();
        String t = "Total cost over " + price.getLifespan() + " years";
        if (specs.isBudgetEnabled()) {
            t += " (" + "<$" + specs.getMaximumBudget() + ")";
        }
        costPanel.setBorder(EnergyPanel.createTitledBorder(t, true));
        packingDensityBar.setValue((float) (reflectingArea / foundation.getArea()));
    } else {
        final List<ParabolicDish> dishes = foundation.getParabolicDishes();
        if (!dishes.isEmpty()) {
            countBar.setValue(dishes.size());
            moduleCountBar.setValue(dishes.size());
            countPanel.setBorder(EnergyPanel.createTitledBorder("Number of parabolic dishes", true));
            double cost = 0;
            double reflectingArea = 0;
            double rimArea = 0;
            final CspCustomPrice price = Scene.getInstance().getCspCustomPrice();
            for (final ParabolicDish d : dishes) {
                rimArea = d.getRimRadius() * d.getRimRadius() * Math.PI;
                cost += price.getHeliostatUnitPrice() * rimArea;
                reflectingArea += rimArea;
            }
            cost += foundation.getArea() * price.getLandUnitPrice() * price.getLifespan();
            costBar.setValue(Math.round(cost));
            final CspDesignSpecs specs = Scene.getInstance().getCspDesignSpecs();
            String t = "Total cost over " + price.getLifespan() + " years";
            if (specs.isBudgetEnabled()) {
                t += " (" + "<$" + specs.getMaximumBudget() + ")";
            }
            costPanel.setBorder(EnergyPanel.createTitledBorder(t, true));
            packingDensityBar.setValue((float) (reflectingArea / foundation.getArea()));
        } else {
            final List<FresnelReflector> fresnels = foundation.getFresnelReflectors();
            if (fresnels.isEmpty()) {
                final List<Mirror> mirrors = foundation.getHeliostats();
                countBar.setValue(mirrors.size());
                moduleCountBar.setValue(mirrors.size());
                countPanel.setBorder(EnergyPanel.createTitledBorder("Number of heliostats", true));
                double cost = 0;
                double reflectingArea = 0;
                double mirrorArea = 0;
                final CspCustomPrice price = Scene.getInstance().getCspCustomPrice();
                final ArrayList<Foundation> towers = new ArrayList<Foundation>();
                for (final Mirror m : mirrors) {
                    mirrorArea = m.getMirrorWidth() * m.getMirrorHeight();
                    cost += price.getHeliostatUnitPrice() * mirrorArea;
                    reflectingArea += mirrorArea;
                    if (m.getReceiver() != null) {
                        if (!towers.contains(m.getReceiver())) {
                            towers.add(m.getReceiver());
                        }
                    }
                }
                if (!mirrors.isEmpty()) {
                    cost += foundation.getArea() * price.getLandUnitPrice() * price.getLifespan();
                    if (!towers.isEmpty()) {
                        for (final Foundation tower : towers) {
                            cost += price.getTowerUnitPrice() * tower.getSolarReceiverHeight(0) * Scene.getInstance().getAnnotationScale();
                        }
                    }
                } else {
                    if (foundation.hasSolarReceiver()) {
                        cost += price.getTowerUnitPrice() * foundation.getSolarReceiverHeight(0) * Scene.getInstance().getAnnotationScale();
                    }
                }
                costBar.setValue(Math.round(cost));
                final CspDesignSpecs specs = Scene.getInstance().getCspDesignSpecs();
                String t = "Total cost over " + price.getLifespan() + " years";
                if (specs.isBudgetEnabled()) {
                    t += " (" + "<$" + specs.getMaximumBudget() + ")";
                }
                costPanel.setBorder(EnergyPanel.createTitledBorder(t, true));
                packingDensityBar.setValue((float) (reflectingArea / foundation.getArea()));
            } else {
                countBar.setValue(fresnels.size());
                int totalModules = 0;
                for (final FresnelReflector r : fresnels) {
                    totalModules += r.getNumberOfModules();
                }
                moduleCountBar.setValue(totalModules);
                countPanel.setBorder(EnergyPanel.createTitledBorder("Number of Fresnel reflectors", true));
                double cost = 0;
                double reflectingArea = 0;
                double unitArea = 0;
                final CspCustomPrice price = Scene.getInstance().getCspCustomPrice();
                for (final FresnelReflector r : fresnels) {
                    unitArea = r.getLength() * r.getModuleWidth();
                    cost += price.getFresnelReflectorUnitPrice() * unitArea;
                    reflectingArea += unitArea;
                }
                cost += foundation.getArea() * price.getLandUnitPrice() * price.getLifespan();
                costBar.setValue(Math.round(cost));
                final CspDesignSpecs specs = Scene.getInstance().getCspDesignSpecs();
                String t = "Total cost over " + price.getLifespan() + " years";
                if (specs.isBudgetEnabled()) {
                    t += " (" + "<$" + specs.getMaximumBudget() + ")";
                }
                costPanel.setBorder(EnergyPanel.createTitledBorder(t, true));
                packingDensityBar.setValue((float) (reflectingArea / foundation.getArea()));
            }
        }
    }
}
Also used : ParabolicTrough(org.concord.energy3d.model.ParabolicTrough) FresnelReflector(org.concord.energy3d.model.FresnelReflector) ArrayList(java.util.ArrayList) ParabolicDish(org.concord.energy3d.model.ParabolicDish) CspDesignSpecs(org.concord.energy3d.simulation.CspDesignSpecs) CspCustomPrice(org.concord.energy3d.simulation.CspCustomPrice) Foundation(org.concord.energy3d.model.Foundation) Mirror(org.concord.energy3d.model.Mirror)

Example 44 with ParabolicTrough

use of org.concord.energy3d.model.ParabolicTrough 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();
        }
    });
}
Also used : ParabolicTrough(org.concord.energy3d.model.ParabolicTrough) NodeState(org.concord.energy3d.model.NodeState) Wall(org.concord.energy3d.model.Wall) UserData(org.concord.energy3d.model.UserData) Node(com.ardor3d.scenegraph.Node) TitledBorder(javax.swing.border.TitledBorder) Rack(org.concord.energy3d.model.Rack) Roof(org.concord.energy3d.model.Roof) Tree(org.concord.energy3d.model.Tree) Foundation(org.concord.energy3d.model.Foundation) List(java.util.List) HousePart(org.concord.energy3d.model.HousePart) FoundationPolygon(org.concord.energy3d.model.FoundationPolygon) Human(org.concord.energy3d.model.Human) Window(org.concord.energy3d.model.Window) Floor(org.concord.energy3d.model.Floor) FresnelReflector(org.concord.energy3d.model.FresnelReflector) GregorianCalendar(java.util.GregorianCalendar) Calendar(java.util.Calendar) Mesh(com.ardor3d.scenegraph.Mesh) ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) Vector3(com.ardor3d.math.Vector3) Door(org.concord.energy3d.model.Door) ParabolicDish(org.concord.energy3d.model.ParabolicDish) ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) OrientedBoundingBox(com.ardor3d.bounding.OrientedBoundingBox) SolarPanel(org.concord.energy3d.model.SolarPanel) Mirror(org.concord.energy3d.model.Mirror) Sensor(org.concord.energy3d.model.Sensor)

Aggregations

ParabolicTrough (org.concord.energy3d.model.ParabolicTrough)44 HousePart (org.concord.energy3d.model.HousePart)30 Foundation (org.concord.energy3d.model.Foundation)22 FresnelReflector (org.concord.energy3d.model.FresnelReflector)18 Mirror (org.concord.energy3d.model.Mirror)17 ParabolicDish (org.concord.energy3d.model.ParabolicDish)17 Rack (org.concord.energy3d.model.Rack)16 SolarPanel (org.concord.energy3d.model.SolarPanel)14 Window (org.concord.energy3d.model.Window)14 Roof (org.concord.energy3d.model.Roof)10 Wall (org.concord.energy3d.model.Wall)10 Door (org.concord.energy3d.model.Door)9 ArrayList (java.util.ArrayList)6 Calendar (java.util.Calendar)5 List (java.util.List)5 JDialog (javax.swing.JDialog)4 Tree (org.concord.energy3d.model.Tree)4 ReadOnlyVector3 (com.ardor3d.math.type.ReadOnlyVector3)3 Human (org.concord.energy3d.model.Human)3 UserData (org.concord.energy3d.model.UserData)3