From 98f7a407673ec85e1fd17d4ddad48f9fe4eb184b Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 31 Aug 2026 12:05:55 +0200 Subject: [PATCH 1/2] Add a test for #5645 --- ruby/test/Issue_5645_Test.rb | 60 ++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 ruby/test/Issue_5645_Test.rb diff --git a/ruby/test/Issue_5645_Test.rb b/ruby/test/Issue_5645_Test.rb new file mode 100644 index 0000000000..cc2acf1564 --- /dev/null +++ b/ruby/test/Issue_5645_Test.rb @@ -0,0 +1,60 @@ +######################################################################################################################## +# OpenStudio(R), Copyright (c) Alliance for Energy Innovation, LLC. +# See also https://openstudio.net/license +######################################################################################################################## + +require 'openstudio' +require 'minitest/autorun' + +# Regression test for #5645: SWIG 4.4.0 broke methods taking a std::vector parameter where T is +# only forward-declared in the module that defines the method, and the real type (plus its +# %template(...Vector)) lives in a separate, dependent SWIG module. +class Issue_5645_Test < Minitest::Test + def test_ShadowCalculation_addShadingZoneGroup + model = OpenStudio::Model::Model.new + zone = OpenStudio::Model::ThermalZone.new(model) + sc = model.getShadowCalculation + + zone_vector = OpenStudio::Model::ThermalZoneVector.new + zone_vector.push(zone) + + assert(sc.addShadingZoneGroup(zone_vector)) + zones = sc.getShadingZoneGroup(0) + assert_equal(1, zones.size) + assert_equal(zone.handle, zones[0].handle) + end + + def test_ShadingControl_addSubSurfaces_setSubSurfaces + model = OpenStudio::Model::Model.new + blind = OpenStudio::Model::Blind.new(model) + shadingControl = OpenStudio::Model::ShadingControl.new(blind) + + vertices1 = OpenStudio::Point3dVector.new + vertices1.push(OpenStudio::Point3d.new(0, 0, 1)) + vertices1.push(OpenStudio::Point3d.new(0, 0, 0)) + vertices1.push(OpenStudio::Point3d.new(1, 0, 0)) + vertices1.push(OpenStudio::Point3d.new(1, 0, 1)) + subSurface1 = OpenStudio::Model::SubSurface.new(vertices1, model) + + vertices2 = OpenStudio::Point3dVector.new + vertices2.push(OpenStudio::Point3d.new(0, 1, 1)) + vertices2.push(OpenStudio::Point3d.new(0, 1, 0)) + vertices2.push(OpenStudio::Point3d.new(1, 1, 0)) + vertices2.push(OpenStudio::Point3d.new(1, 1, 1)) + subSurface2 = OpenStudio::Model::SubSurface.new(vertices2, model) + + subSurfaces = OpenStudio::Model::SubSurfaceVector.new + subSurfaces.push(subSurface1) + subSurfaces.push(subSurface2) + + assert_equal(0, shadingControl.numberofSubSurfaces) + assert(shadingControl.addSubSurfaces(subSurfaces)) + assert_equal(2, shadingControl.numberofSubSurfaces) + + shadingControl.removeAllSubSurfaces + assert_equal(0, shadingControl.numberofSubSurfaces) + + assert(shadingControl.setSubSurfaces(subSurfaces)) + assert_equal(2, shadingControl.numberofSubSurfaces) + end +end From 940e5a1c296f3abe1c663ca32127c47197fd479c Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 31 Aug 2026 15:45:32 +0200 Subject: [PATCH 2/2] Fix #5645 via a workaround. REVERT when upgrading to SWIG 4.6.0+ https://github.com/swig/swig/pull/3554 --- src/model/ModelGeometry.i | 45 +++++++++++++++++++++++++++++++++++++ src/model/ModelHVAC.i | 37 ++++++++++++++++++++++++++++++ src/model/ModelResources.i | 13 ++++++++--- src/model/ModelSimulation.i | 13 +++++++---- 4 files changed, 101 insertions(+), 7 deletions(-) diff --git a/src/model/ModelGeometry.i b/src/model/ModelGeometry.i index 2207c80b6c..d3fa10bb06 100644 --- a/src/model/ModelGeometry.i +++ b/src/model/ModelGeometry.i @@ -391,6 +391,51 @@ SWIG_MODELOBJECT(ExteriorWaterEquipment, 1); #endif +#if defined(SWIGPYTHON) || defined(SWIGRUBY) + // See ModelResources.i: SWIG >= 4.4.0 cannot resolve std::vector as a parameter or + // return type there since SubSurface is only forward-declared in that module. Reimplement these + // here where SubSurface is fully known, then rebind them onto ShadingControl below. + %inline { + namespace openstudio { + namespace model { + std::vector getSubSurfaces(const openstudio::model::ShadingControl& sc) { + return sc.subSurfaces(); + } + bool addSubSurfacesForShadingControl(openstudio::model::ShadingControl sc, const std::vector& subSurfaces) { + return sc.addSubSurfaces(subSurfaces); + } + bool setSubSurfacesForShadingControl(openstudio::model::ShadingControl sc, const std::vector& subSurfaces) { + return sc.setSubSurfaces(subSurfaces); + } + } + } + } +#endif + +#if defined SWIGPYTHON + %pythoncode %{ + def _subSurfaces(self): + return getSubSurfaces(self) + openstudiomodelresources.ShadingControl.subSurfaces = _subSurfaces + + def _addSubSurfaces(self, subSurfaces): + return addSubSurfacesForShadingControl(self, subSurfaces) + openstudiomodelresources.ShadingControl.addSubSurfaces = _addSubSurfaces + + def _setSubSurfaces(self, subSurfaces): + return setSubSurfacesForShadingControl(self, subSurfaces) + openstudiomodelresources.ShadingControl.setSubSurfaces = _setSubSurfaces + %} +#endif + +#if defined SWIGRUBY + %init %{ + rb_eval_string("OpenStudio::Model::ShadingControl.class_eval { define_method(:subSurfaces) { OpenStudio::Model.getSubSurfaces(self); } }"); + rb_eval_string("OpenStudio::Model::ShadingControl.class_eval { define_method(:addSubSurfaces) { |subSurfaces| OpenStudio::Model.addSubSurfacesForShadingControl(self, subSurfaces); } }"); + rb_eval_string("OpenStudio::Model::ShadingControl.class_eval { define_method(:setSubSurfaces) { |subSurfaces| OpenStudio::Model.setSubSurfacesForShadingControl(self, subSurfaces); } }"); + %} +#endif + #if defined(SWIGCSHARP) //%pragma(csharp) imclassimports=%{ %pragma(csharp) moduleimports=%{ diff --git a/src/model/ModelHVAC.i b/src/model/ModelHVAC.i index c8145dd8f2..1151d73987 100644 --- a/src/model/ModelHVAC.i +++ b/src/model/ModelHVAC.i @@ -482,6 +482,43 @@ SWIG_MODELOBJECT(LoadingIndex, 1); } // %inline #endif +#if defined(SWIGPYTHON) || defined(SWIGRUBY) + // See ModelSimulation.i: SWIG >= 4.4.0 cannot resolve std::vector as a parameter or + // return type there since ThermalZone is only forward-declared in that module. Reimplement both + // here where ThermalZone is fully known, then rebind them onto ShadowCalculation below. + %inline { + namespace openstudio { + namespace model { + std::vector getShadingZoneGroup(const openstudio::model::ShadowCalculation& sc, unsigned groupIndex) { + return sc.getShadingZoneGroup(groupIndex); + } + bool addShadingZoneGroup(openstudio::model::ShadowCalculation sc, const std::vector& thermalZones) { + return sc.addShadingZoneGroup(thermalZones); + } + } + } + } +#endif + +#if defined SWIGPYTHON + %pythoncode %{ + def _getShadingZoneGroup(self, groupIndex): + return getShadingZoneGroup(self, groupIndex) + openstudiomodelsimulation.ShadowCalculation.getShadingZoneGroup = _getShadingZoneGroup + + def _addShadingZoneGroup(self, thermalZones): + return addShadingZoneGroup(self, thermalZones) + openstudiomodelsimulation.ShadowCalculation.addShadingZoneGroup = _addShadingZoneGroup + %} +#endif + +#if defined SWIGRUBY + %init %{ + rb_eval_string("OpenStudio::Model::ShadowCalculation.class_eval { define_method(:getShadingZoneGroup) { |groupIndex| OpenStudio::Model.getShadingZoneGroup(self, groupIndex); } }"); + rb_eval_string("OpenStudio::Model::ShadowCalculation.class_eval { define_method(:addShadingZoneGroup) { |thermalZones| OpenStudio::Model.addShadingZoneGroup(self, thermalZones); } }"); + %} +#endif + #if defined(SWIGCSHARP) //%pragma(csharp) imclassimports=%{ %pragma(csharp) moduleimports=%{ diff --git a/src/model/ModelResources.i b/src/model/ModelResources.i index 07f47e456a..e00d8122c8 100644 --- a/src/model/ModelResources.i +++ b/src/model/ModelResources.i @@ -25,13 +25,10 @@ %ignore openstudio::model::SpaceType::spaces; %ignore openstudio::model::SpaceLoadDefinition::instances; %ignore openstudio::model::ExteriorLoadDefinition::instances; - %ignore openstudio::model::ShadingControl::subSurfaces; %ignore openstudio::model::ShadingControl::subSurfaceIndex; %ignore openstudio::model::ShadingControl::addSubSurface; %ignore openstudio::model::ShadingControl::setSubSurfaceIndex; %ignore openstudio::model::ShadingControl::removeSubSurface(const SubSurface& subSurface); // The unsigned index overload is fine - %ignore openstudio::model::ShadingControl::addSubSurfaces; - %ignore openstudio::model::ShadingControl::setSubSurfaces; // CoilCoolingDX is defined in StraightComponent.i %ignore openstudio::model::CoilCoolingDXCurveFitPerformance::coilCoolingDXs; @@ -44,6 +41,16 @@ #endif +// Note JM 2026-08-31: SWIG >= 4.4.0 cannot properly resolve std::vector as a parameter +// or return type here, because SubSurface is only forward-declared in this module: the real type +// and its %template(SubSurfaceVector) live in ModelGeometry.i, which imports this module. This used +// to work with SWIG 4.1.1. Ignore these here (for all languages, not just C#/Java) and +// reimplement/rebind them in ModelGeometry.i where SubSurface is fully known. +// See https://github.com/NatLabRockies/OpenStudio/issues/5645 +%ignore openstudio::model::ShadingControl::subSurfaces; +%ignore openstudio::model::ShadingControl::addSubSurfaces; +%ignore openstudio::model::ShadingControl::setSubSurfaces; + #if defined(SWIGJAVA) %ignore openstudio::model::OpaqueMaterial::solarAbsorptance; %ignore openstudio::model::OpaqueMaterial::visibleAbsorptance; diff --git a/src/model/ModelSimulation.i b/src/model/ModelSimulation.i index b1046e325e..f543bb4d00 100644 --- a/src/model/ModelSimulation.i +++ b/src/model/ModelSimulation.i @@ -28,12 +28,17 @@ %ignore openstudio::model::WeatherFile::site; %ignore openstudio::model::ClimateZones::site; - // Note JM 2020-03-11: Ignoring this, will reimplement later in ModelHVAC.i using partial classes - %ignore openstudio::model::ShadowCalculation::addShadingZoneGroup; - %ignore openstudio::model::ShadowCalculation::getShadingZoneGroup; - #endif +// Note JM 2026-08-31: SWIG >= 4.4.0 cannot properly resolve std::vector as a parameter +// or return type here, because ThermalZone is only forward-declared in this module: the real type +// and its %template(ThermalZoneVector) live in ModelHVAC.i, which imports this module. This used to +// work with SWIG 4.1.1. Ignore both here (for all languages, not just C#) and reimplement/rebind them +// in ModelHVAC.i where ThermalZone is fully known. +// See https://github.com/NatLabRockies/OpenStudio/issues/5645 +%ignore openstudio::model::ShadowCalculation::addShadingZoneGroup; +%ignore openstudio::model::ShadowCalculation::getShadingZoneGroup; + #if defined SWIGPYTHON %pythoncode %{ Model = openstudiomodelcore.Model