Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
508 changes: 508 additions & 0 deletions src/openstudio_app/Resources/default/hvac_library.osm

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion src/openstudio_lib/GridItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
#include <openstudio/model/ZoneHVACTerminalUnitVariableRefrigerantFlow_Impl.hpp>

#include "../openstudio_qt_utils/Utilities.hpp"
#include "../utilities/HeatPumpAirToWaterPlacement.hpp"

#include <openstudio/utilities/idd/IddEnums.hxx>

Expand Down Expand Up @@ -241,7 +242,8 @@ void ModelObjectGraphicsItem::setModelObject(model::OptionalModelObject modelObj

if (auto comp_ = m_modelObject->optionalCast<model::HVACComponent>()) {
setAcceptDrops(true);
setDeletable(comp_->isRemovable());
// A HeatPumpAirToWater operation mode isn't removable by itself, but can be taken off its loop
setDeletable(comp_->isRemovable() || heatPumpAirToWaterForMode(comp_.get()));
if (isNotSplitterMixerNodesPred(comp_.get())) {
setDraggable(true);
}
Expand Down
56 changes: 55 additions & 1 deletion src/openstudio_lib/HVACSystemsController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@
#include "MainRightColumnController.hpp"
#include "../shared_gui_components/OSViewSwitcher.hpp"
#include "../utilities/CloneFixup.hpp"
#include "../utilities/HeatPumpAirToWaterPlacement.hpp"

#include <openstudio/model/ModelObject.hpp>
#include <openstudio/model/HVACComponent.hpp>
#include <openstudio/model/HVACComponent_Impl.hpp>
#include <openstudio/model/HeatPumpAirToWater.hpp>
#include <openstudio/model/HeatPumpAirToWater_Impl.hpp>
#include <openstudio/model/WaterHeaterMixed.hpp>
#include <openstudio/model/WaterHeaterMixed_Impl.hpp>
#include <openstudio/model/WaterHeaterSizing.hpp>
Expand Down Expand Up @@ -131,6 +134,7 @@

#include <map>

#include <QCoreApplication>
#include <QMessageBox>
#include <QTimer>
#include <QPushButton>
Expand All @@ -147,6 +151,40 @@ const QString SHW = "SHW";
const QString REFRIGERATION = "REFRIGERATION";
const QString VRF = "VRF";

namespace {
// Asks which of a HeatPumpAirToWater's operation modes to place on `plantLoop`, preselecting the one
// suggested by the loop's sizing type. Returns none if the user cancels.
boost::optional<HeatPumpAirToWaterType> askHeatPumpAirToWaterMode(const model::PlantLoop& plantLoop, QWidget* parent) {
QMessageBox message(parent);
message.setWindowTitle(QCoreApplication::translate("openstudio::HVACLayoutController", "Air to Water Heat Pump"));
message.setText(QCoreApplication::translate("openstudio::HVACLayoutController",
"Which operation mode of this air to water heat pump should be placed on this loop?"));
message.setInformativeText(QCoreApplication::translate(
"openstudio::HVACLayoutController", "The other mode can be placed on another plant loop later by dragging it from the My Model tab."));
QAbstractButton* heatingButton =
message.addButton(QCoreApplication::translate("openstudio::HVACLayoutController", "Heating"), QMessageBox::AcceptRole);
QAbstractButton* coolingButton =
message.addButton(QCoreApplication::translate("openstudio::HVACLayoutController", "Cooling"), QMessageBox::AcceptRole);
message.addButton(QMessageBox::Cancel);

const auto suggested = suggestedHeatPumpAirToWaterMode(plantLoop);
if (suggested && suggested.get() == HeatPumpAirToWaterType::Cooling) {
message.setDefaultButton(qobject_cast<QPushButton*>(coolingButton));
} else {
message.setDefaultButton(qobject_cast<QPushButton*>(heatingButton));
}

message.exec();
if (message.clickedButton() == heatingButton) {
return HeatPumpAirToWaterType::Heating;
}
if (message.clickedButton() == coolingButton) {
return HeatPumpAirToWaterType::Cooling;
}
return boost::none;
}
} // namespace

HVACSystemsController::HVACSystemsController(bool isIP, const model::Model& model)
: m_hvacSystemsView(new HVACSystemsView()), m_updateMutex(new QMutex()), m_model(model), m_isIP(isIP) {

Expand Down Expand Up @@ -554,7 +592,19 @@ void HVACLayoutController::addLibraryObjectToModelNode(const OSItemId& itemId, m

bool added = false;

if (boost::optional<model::HVACComponent> hvacComponent = object->optionalCast<model::HVACComponent>()) {
if (boost::optional<model::HeatPumpAirToWater> heatPump = object->optionalCast<model::HeatPumpAirToWater>()) {
// The wrapper can't be placed on a loop itself: one of its heating/cooling operation modes goes there instead
if (boost::optional<model::PlantLoop> plant = comp.plantLoop()) {
boost::optional<HeatPumpAirToWaterType> mode = askHeatPumpAirToWaterMode(plant.get(), m_hvacSystemsController->hvacSystemsView());
if (!mode) {
if (remove) {
object->remove();
}
return;
}
added = addHeatPumpAirToWaterModeToLoop(heatPump.get(), mode.get(), comp);
}
} else if (boost::optional<model::HVACComponent> hvacComponent = object->optionalCast<model::HVACComponent>()) {
if (boost::optional<model::Node> node = comp.optionalCast<model::Node>()) {
// Note: Julien Marrec, 2018-01-04
// When you have a WaterToWaterComponent that has a tertiaryPlantLoop, you should override the addToNode method
Expand Down Expand Up @@ -634,6 +684,10 @@ void HVACLayoutController::removeModelObject(model::ModelObject& modelObject) {

boost::optional<model::Loop> loop = m_hvacSystemsController->currentLoop();

if (removeHeatPumpAirToWaterModeFromLoop(modelObject)) {
return;
}

if (loop) {
if (boost::optional<model::WaterToWaterComponent> comp = modelObject.optionalCast<model::WaterToWaterComponent>()) {
boost::optional<model::PlantLoop> plant = comp->plantLoop();
Expand Down
99 changes: 99 additions & 0 deletions src/openstudio_lib/InspectorView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "OSDocument.hpp"
#include "ZoneChooserView.hpp"
#include "EMSInspectorView.hpp"
#include "../utilities/HeatPumpAirToWaterPlacement.hpp"

#include <openstudio/model/AirLoopHVACReturnPlenum.hpp>
#include <openstudio/model/AirLoopHVACReturnPlenum_Impl.hpp>
Expand Down Expand Up @@ -75,6 +76,10 @@
#include <openstudio/model/FanSystemModel_Impl.hpp>
#include <openstudio/model/HVACComponent.hpp>
#include <openstudio/model/HVACComponent_Impl.hpp>
#include <openstudio/model/HeatPumpAirToWaterCooling.hpp>
#include <openstudio/model/HeatPumpAirToWaterCooling_Impl.hpp>
#include <openstudio/model/HeatPumpAirToWaterHeating.hpp>
#include <openstudio/model/HeatPumpAirToWaterHeating_Impl.hpp>
#include <openstudio/model/ModelObject_Impl.hpp>
#include <openstudio/model/RefrigerationWalkIn.hpp>
#include <openstudio/model/RefrigerationWalkInZoneBoundary.hpp>
Expand Down Expand Up @@ -129,6 +134,7 @@
#include <QPainter>
#include <QPixmap>
#include <QPushButton>
#include <QScrollArea>
#include <QTimer>
#include <QToolButton>
#include <QVBoxLayout>
Expand Down Expand Up @@ -593,6 +599,18 @@ void InspectorView::layoutModelObject(openstudio::model::OptionalModelObject& mo

connect(static_cast<ZoneHVACPackagedTerminalHeatPumpInspectorView*>(m_currentView),
&ZoneHVACPackagedTerminalHeatPumpInspectorView::removeFromLoopClicked, this, &InspectorView::removeFromLoopClicked);
} else if (heatPumpAirToWaterForMode(modelObject.get())) {
if (m_currentView) {
delete m_currentView;
}

m_currentView = new HeatPumpAirToWaterModeInspectorView();
connect(this, &InspectorView::toggleUnitsClicked, m_currentView, &BaseInspectorView::toggleUnitsClicked);
connect(this, &InspectorView::toggleDisplayAdditionalPropsClicked, m_currentView, &BaseInspectorView::toggleDisplayAdditionalPropsClicked);

m_currentView->layoutModelObject(modelObject.get(), readOnly, displayIP, displayAdditionalProps);

m_vLayout->addWidget(m_currentView);
} else if (boost::optional<model::WaterHeaterHeatPump> component = modelObject->optionalCast<model::WaterHeaterHeatPump>())

{
Expand Down Expand Up @@ -908,6 +926,87 @@ void GenericInspectorView::layoutModelObject(model::ModelObject& modelObject, bo
m_emsSensorView->layoutModelObject(modelObject);
}

namespace {

// An InspectorGadget without its own scroll area, so several can be stacked in one scrolling page
class StackedInspectorGadget : public InspectorGadget
{
public:
StackedInspectorGadget(openstudio::WorkspaceObject& workspaceObj, bool locked)
: InspectorGadget(workspaceObj, 0, nullptr, false, true, true, locked) {}
};

} // namespace

HeatPumpAirToWaterModeInspectorView::HeatPumpAirToWaterModeInspectorView(QWidget* parent) : BaseInspectorView(parent) {
auto* scrollArea = new QScrollArea();
scrollArea->setWidgetResizable(true);
scrollArea->setFrameStyle(QFrame::NoFrame);

auto* gadgetsWidget = new QWidget();
m_gadgetsLayout = new QVBoxLayout(gadgetsWidget);
m_gadgetsLayout->setSpacing(0);
m_gadgetsLayout->setContentsMargins(0, 0, 0, 0);
m_gadgetsLayout->addStretch();
scrollArea->setWidget(gadgetsWidget);

m_libraryTabWidget->addTab(scrollArea, ":/images/properties_icon_on.png", ":/images/properties_icon_off.png");

m_emsActuatorView = new EMSInspectorView(nullptr, EMSInspectorView::Type::ACTUATOR);
m_libraryTabWidget->addTab(m_emsActuatorView, ":/images/controller_icon_on.png", ":/images/controller_icon_off.png");

m_emsSensorView = new EMSInspectorView(nullptr, EMSInspectorView::Type::SENSOR);
m_libraryTabWidget->addTab(m_emsSensorView, ":/images/controller_icon_on.png", ":/images/controller_icon_off.png");
}

void HeatPumpAirToWaterModeInspectorView::layoutModelObject(model::ModelObject& modelObject, bool readOnly, bool displayIP,
bool displayAdditionalProps) {
const bool force = true;
const bool recursive = true;
int insertIndex = 0;

auto addGadget = [&](model::ModelObject object, bool hideChildren) {
auto* gadget = new StackedInspectorGadget(object, readOnly);
// The gadget lays the object out in IP without additional properties when constructed; each change below rebuilds it
if (!displayIP) {
gadget->setUnitSystem(InspectorGadget::SI);
}
if (displayAdditionalProps) {
gadget->setDisplayAdditionalProps(true);
}
if (hideChildren) {
gadget->layoutModelObj(object, force, recursive, readOnly, hideChildren);
}
connect(this, &HeatPumpAirToWaterModeInspectorView::toggleUnitsClicked, gadget, &InspectorGadget::toggleUnitsClicked);
connect(this, &HeatPumpAirToWaterModeInspectorView::toggleDisplayAdditionalPropsClicked, gadget,
&InspectorGadget::toggleDisplayAdditionalPropsClicked);
connect(gadget, &InspectorGadget::workspaceObjectRemoved, this, &BaseInspectorView::workspaceObjectRemoved);
m_gadgetsLayout->insertWidget(insertIndex++, gadget);
};

// The wrapper's own children are both operation modes, so hide them there and show the selected mode right
// under the wrapper, followed by the other mode
boost::optional<model::HeatPumpAirToWater> heatPump = heatPumpAirToWaterForMode(modelObject);
if (heatPump) {
addGadget(heatPump.get(), true);
}
addGadget(modelObject, false);
if (heatPump) {
boost::optional<model::ModelObject> otherMode;
if (heatPumpAirToWaterType(modelObject) == HeatPumpAirToWaterType::Heating) {
otherMode = heatPump->coolingOperationMode();
} else {
otherMode = heatPump->heatingOperationMode();
}
if (otherMode) {
addGadget(otherMode.get(), false);
}
}

m_emsActuatorView->layoutModelObject(modelObject);
m_emsSensorView->layoutModelObject(modelObject);
}

NewPlenumDialog::NewPlenumDialog(QWidget* parent) : QDialog(parent) {
auto* mainVLayout = new QVBoxLayout();
mainVLayout->setAlignment(Qt::AlignTop);
Expand Down
19 changes: 19 additions & 0 deletions src/openstudio_lib/InspectorView.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,25 @@ class ScheduleRulesetInspectorView : public BaseInspectorView
virtual void layoutModelObject(model::ModelObject& modelObject, bool readOnly, bool displayIP, bool displayAdditionalProps = false) override;
};

// For a HeatPumpAirToWater heating or cooling operation mode: shows the owning HeatPumpAirToWater first,
// then the selected mode, then the other mode, since all three are edited as one piece of equipment
class HeatPumpAirToWaterModeInspectorView : public BaseInspectorView
{
Q_OBJECT;

public:
explicit HeatPumpAirToWaterModeInspectorView(QWidget* parent = nullptr);

virtual ~HeatPumpAirToWaterModeInspectorView() {}

void layoutModelObject(model::ModelObject& modelObject, bool readOnly, bool displayIP, bool displayAdditionalProps = false) override;

private:
QVBoxLayout* m_gadgetsLayout;
EMSInspectorView* m_emsActuatorView;
EMSInspectorView* m_emsSensorView;
};

} // namespace openstudio

#endif // OPENSTUDIO_INSPECTORVIEW_HPP
21 changes: 15 additions & 6 deletions src/openstudio_lib/MainRightColumnController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1047,15 +1047,20 @@ void MainRightColumnController::configureForHVACSystemsSubTab(int subTabID) {
myModelList->addModelObjectCategoryPlaceholder(tr("Zone HVAC"));

// Central components and coils
myModelList->addModelObjectType(IddObjectType::OS_HeatPump_WaterToWater_EquationFit_Heating, tr("Heat Pump - Water to Water - Heating"));
myModelList->addModelObjectType(IddObjectType::OS_HeatPump_WaterToWater_EquationFit_Cooling, tr("Heat Pump - Water to Water - Cooling"));
myModelList->addModelObjectType(IddObjectType::OS_HeatExchanger_FluidToFluid, tr("Heat Exchanger Fluid To Fluid"));
myModelList->addModelObjectCategoryPlaceholder(tr("Heat Exchangers"));
myModelList->addModelObjectType(IddObjectType::OS_Coil_Heating_Water, tr("Coil Heating Water"));
myModelList->addModelObjectType(IddObjectType::OS_Coil_Cooling_Water, tr("Coil Cooling Water"));
myModelList->addModelObjectCategoryPlaceholder(tr("Coils"));
myModelList->addModelObjectType(IddObjectType::OS_HeatPump_WaterToWater_EquationFit_Heating, tr("Heat Pump - Water to Water - Heating"));
myModelList->addModelObjectType(IddObjectType::OS_HeatPump_WaterToWater_EquationFit_Cooling, tr("Heat Pump - Water to Water - Cooling"));
myModelList->addModelObjectType(IddObjectType::OS_HeatPump_PlantLoop_EIR_Heating, tr("Heat Pump - Plant Loop EIR - Heating"));
myModelList->addModelObjectType(IddObjectType::OS_HeatPump_PlantLoop_EIR_Cooling, tr("Heat Pump - Plant Loop EIR - Cooling"));
myModelList->addModelObjectType(IddObjectType::OS_HeatPump_AirToWater_FuelFired_Heating, tr("Heat Pump - Air to Water Fuel Fired - Heating"));
myModelList->addModelObjectType(IddObjectType::OS_HeatPump_AirToWater_FuelFired_Cooling, tr("Heat Pump - Air to Water Fuel Fired - Cooling"));
myModelList->addModelObjectType(IddObjectType::OS_HeatPump_AirToWater, tr("Heat Pump - Air to Water"));
myModelList->addModelObjectType(IddObjectType::OS_CentralHeatPumpSystem, tr("Central Heat Pump System"));
myModelList->addModelObjectCategoryPlaceholder(tr("Heat Pumps"));
myModelList->addModelObjectCategoryPlaceholder(tr("Plant Loop Heat Pumps"));
myModelList->addModelObjectType(IddObjectType::OS_Chiller_Electric_EIR, tr("Chiller - Electric EIR"));
myModelList->addModelObjectType(IddObjectType::OS_Chiller_Absorption, tr("Chiller - Absorption"));
myModelList->addModelObjectType(IddObjectType::OS_Chiller_Absorption_Indirect, tr("Chiller - Indirect Absorption"));
Expand Down Expand Up @@ -1169,7 +1174,13 @@ void MainRightColumnController::configureForHVACSystemsSubTab(int subTabID) {
libraryWidget->addModelObjectCategoryPlaceholder(tr("Humidifiers"));
libraryWidget->addModelObjectType(IddObjectType::OS_HeatPump_WaterToWater_EquationFit_Heating, tr("Heat Pump - Water to Water - Heating"));
libraryWidget->addModelObjectType(IddObjectType::OS_HeatPump_WaterToWater_EquationFit_Cooling, tr("Heat Pump - Water to Water - Cooling"));
libraryWidget->addModelObjectCategoryPlaceholder(tr("Heat Pumps"));
libraryWidget->addModelObjectType(IddObjectType::OS_HeatPump_PlantLoop_EIR_Heating, tr("Heat Pump - Plant Loop EIR - Heating"));
libraryWidget->addModelObjectType(IddObjectType::OS_HeatPump_PlantLoop_EIR_Cooling, tr("Heat Pump - Plant Loop EIR - Cooling"));
libraryWidget->addModelObjectType(IddObjectType::OS_HeatPump_AirToWater_FuelFired_Heating, tr("Heat Pump - Air to Water Fuel Fired - Heating"));
libraryWidget->addModelObjectType(IddObjectType::OS_HeatPump_AirToWater_FuelFired_Cooling, tr("Heat Pump - Air to Water Fuel Fired - Cooling"));
libraryWidget->addModelObjectType(IddObjectType::OS_HeatPump_AirToWater, tr("Heat Pump - Air to Water"));
libraryWidget->addModelObjectType(IddObjectType::OS_CentralHeatPumpSystem, tr("Central Heat Pump System"));
libraryWidget->addModelObjectCategoryPlaceholder(tr("Plant Loop Heat Pumps"));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it doesn't matter but shouldn't all the "Plant Loop Heat Pumps" be together?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Central Heat Pump System is now in Plant Loop Heat Pumps in the Library as well, matching My Model, and the separate "Central Heat Pump Systems" category is gone.

libraryWidget->addModelObjectType(IddObjectType::OS_HeatExchanger_FluidToFluid, tr("Heat Exchanger Fluid To Fluid"));
libraryWidget->addModelObjectType(IddObjectType::OS_HeatExchanger_AirToAir_SensibleAndLatent, tr("Heat Exchanger Air To Air Sensible and Latent"));
libraryWidget->addModelObjectCategoryPlaceholder(tr("Heat Exchangers"));
Expand Down Expand Up @@ -1210,8 +1221,6 @@ void MainRightColumnController::configureForHVACSystemsSubTab(int subTabID) {
libraryWidget->addModelObjectType(IddObjectType::OS_CoolingTower_SingleSpeed, tr("Cooling Tower Single Speed"));
libraryWidget->addModelObjectType(IddObjectType::OS_CoolingTower_VariableSpeed, tr("Cooling Tower Variable Speed"));
libraryWidget->addModelObjectCategoryPlaceholder(tr("Cooling Towers"));
libraryWidget->addModelObjectType(IddObjectType::OS_CentralHeatPumpSystem, tr("Central Heat Pump System"));
libraryWidget->addModelObjectCategoryPlaceholder(tr("Central Heat Pump Systems"));
libraryWidget->addModelObjectType(IddObjectType::OS_Chiller_Electric_EIR, tr("Chiller - Electric EIR"));
libraryWidget->addModelObjectType(IddObjectType::OS_Chiller_Absorption_Indirect, tr("Chiller - Indirect Absorption"));
libraryWidget->addModelObjectType(IddObjectType::OS_Chiller_Absorption, tr("Chiller - Absorption"));
Expand Down
Binary file added src/openstudio_lib/images/heatpump_airtowater.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think adding something like f(x) or something would be good to indicate the equation fit? I'll leave it up to you, just wanted to suggest it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. The water-to-water heating and cooling icons now show f(x) next to the heat waves or snowflake, and the mini icons have a smaller f(x) above the colour band.

23 changes: 23 additions & 0 deletions src/openstudio_lib/images/svg/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Icon sources

SVG sources for the Plant Loop Heat Pump icons. The app loads the PNGs in `images/` and `images/mini_icons/`,
not these files.

| SVG | PNGs |
|---|---|
| `<name>.svg` | `images/<name>.png` (100 px) and `images/<name>@2x.png` (200 px) |
| `<name>_mini.svg` | `images/mini_icons/<name>.png` (24 px) and `images/mini_icons/<name>@2x.png` (48 px) |

The air-to-water wrapper and its heating and cooling modes share `heatpump_airtowater`.

## Exporting

`export.html` draws one SVG at a given size on a transparent page. Screenshot it with headless Chrome, once per size:

```sh
chrome --headless=new --hide-scrollbars --allow-file-access-from-files --default-background-color=00000000 \
--window-size=200,200 --screenshot=heatpump_airtowater@2x.png \
"file:///<path to this folder>/export.html?f=heatpump_airtowater.svg&s=200"
```

The f(x) labels on the water-to-water (equation fit) icons use the system's Georgia font.
2 changes: 2 additions & 0 deletions src/openstudio_lib/images/svg/export.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<!doctype html><html><head><style>html,body{margin:0;padding:0;background:transparent;overflow:hidden}img{display:block}</style></head>
<body><img id="i"><script>const q=new URLSearchParams(location.search);const i=document.getElementById('i');i.src=q.get('f');i.width=i.height=+q.get('s');</script></body></html>
Loading
Loading