TEST_F(EnergyPlusFixture,ForwardTranslator_ShadingSurface_Space)
{
  Model model;
  
  ThermalZone thermalZone(model);

  Point3dVector points;
  points.push_back(Point3d(0,1,0));
  points.push_back(Point3d(1,1,0));
  points.push_back(Point3d(1,0,0));
  points.push_back(Point3d(0,0,0));

  boost::optional<Space> space = Space::fromFloorPrint(points, 1, model);
  ASSERT_TRUE(space);
  space->setThermalZone(thermalZone);

  ShadingSurfaceGroup shadingSurfaceGroup(model);
  EXPECT_TRUE(shadingSurfaceGroup.setSpace(*space));

  ShadingSurface shadingSurface(points, model);
  EXPECT_TRUE(shadingSurface.setShadingSurfaceGroup(shadingSurfaceGroup));

  ForwardTranslator forwardTranslator;
  Workspace workspace = forwardTranslator.translateModel(model);
  
  ASSERT_EQ(1u, workspace.getObjectsByType(IddObjectType::Zone).size());
  ASSERT_EQ(1u, workspace.getObjectsByType(IddObjectType::Shading_Zone_Detailed).size());

  WorkspaceObject zoneObject = workspace.getObjectsByType(IddObjectType::Zone)[0];
  WorkspaceObject shadingSurfaceObject = workspace.getObjectsByType(IddObjectType::Shading_Zone_Detailed)[0];

  EXPECT_TRUE(shadingSurfaceObject.getTarget(Shading_Zone_DetailedFields::BaseSurfaceName));
}
TEST_F(ModelFixture, ModelObject_Clone_SameModel) {
  // Make model object with resource that has children
  Model original;
  Point3dVector points;
  points.push_back(Point3d(0, 1, 0));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(1, 0, 0));
  Surface surface(points, original);
  Construction construction(original);
  surface.setConstruction(construction);
  construction.standardsInformation(); // creates object
  StandardOpaqueMaterial material(original);
  construction.setLayers(MaterialVector(1u,material));
  EXPECT_EQ(4u,original.numObjects());

  // Clone into same model -- new object with different name. resources reused.
  Surface newSurface = surface.clone(original).cast<Surface>();
  EXPECT_FALSE(newSurface == surface);
  EXPECT_EQ(5u,original.numObjects());
  EXPECT_NE(surface.name().get(),newSurface.name().get());
  ASSERT_TRUE(surface.construction());
  ASSERT_TRUE(newSurface.construction());
  EXPECT_TRUE(surface.construction().get() == newSurface.construction().get());
  EXPECT_TRUE(newSurface.construction().get().cast<LayeredConstruction>().numLayers() == 1u);
}
TEST_F(ModelFixture, InteriorPartitionSurface_DefaultConstruction)
{
  Model model;

  Space space(model);

  Construction construction(model);

  DefaultConstructionSet defaultConstructionSet(model);
  defaultConstructionSet.setInteriorPartitionConstruction(construction);
  space.setDefaultConstructionSet(defaultConstructionSet);

  InteriorPartitionSurfaceGroup group(model);
  group.setSpace(space);

  Point3dVector points;
  points.push_back(Point3d(0, 2, 0));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(1, 0, 0));
  InteriorPartitionSurface surface(points, model);
  
  EXPECT_FALSE(surface.construction());
  
  surface.setInteriorPartitionSurfaceGroup(group);

  ASSERT_TRUE(surface.construction());
  EXPECT_EQ(construction.handle(), surface.construction()->handle());
}
TEST_F(EnergyPlusFixture,ForwardTranslator_Surface_Zone)
{
  Model model;

  ThermalZone thermalZone(model);

  Space space(model);
  space.setThermalZone(thermalZone);
  
  Point3dVector points;
  points.push_back(Point3d(0, 1, 0));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(1, 0, 0));
  points.push_back(Point3d(1, 1, 0));
  Surface surface(points, model);
  surface.setSpace(space);

  ForwardTranslator forwardTranslator;
  Workspace workspace = forwardTranslator.translateModel(model);
  EXPECT_EQ(0u, forwardTranslator.errors().size());
  EXPECT_EQ(0u, forwardTranslator.warnings().size());

  ASSERT_EQ(1u, workspace.getObjectsByType(IddObjectType::BuildingSurface_Detailed).size());
  ASSERT_EQ(1u, workspace.getObjectsByType(IddObjectType::Zone).size());

  WorkspaceObject surfaceObject = workspace.getObjectsByType(IddObjectType::BuildingSurface_Detailed)[0];
  WorkspaceObject zoneObject = workspace.getObjectsByType(IddObjectType::Zone)[0];

  ASSERT_TRUE(surfaceObject.getTarget(BuildingSurface_DetailedFields::ZoneName));
  EXPECT_EQ(zoneObject.handle(), surfaceObject.getTarget(BuildingSurface_DetailedFields::ZoneName)->handle());
}
Exemple #5
0
  bool circularEqual(const Point3dVector& points1, const Point3dVector& points2, double tol)
  {
    unsigned N = points1.size();
    if (N != points2.size()){
      return false;
    }

    if (N == 0){
      return true;
    }

    bool result = false;

    // look for a common starting point
    for (unsigned i = 0; i < N; ++i){
      if (getDistance(points1[0], points2[i]) <= tol){

        result = true;

        // check all other points
        for (unsigned j = 0; j < N; ++j){
          if (getDistance(points1[j], points2[(i + j) % N]) > tol){
            result = false;
            break;
          }
        }
      }

      if (result){
        return result;
      }
    }

    return result;
  }
TEST_F(EnergyPlusFixture,ForwardTranslator_ThermalZone_OneZone_OneSpace_Building)
{
  Model model;

  Point3dVector points;
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(0, 1, 0));
  points.push_back(Point3d(1, 1, 0));
  points.push_back(Point3d(1, 0, 0));

  SpaceType spaceType(model);
  spaceType.setLightingPowerPerFloorArea(1);

  Building building = model.getUniqueModelObject<Building>();
  building.setSpaceType(spaceType);

  ThermalZone zone(model);

  Space space(model);
  space.setThermalZone(zone);

  Surface surface(points, model);
  surface.setSpace(space);

  EXPECT_EQ(1, space.floorArea());
  EXPECT_EQ(1, space.lightingPowerPerFloorArea());

  ForwardTranslator trans;
  Workspace workspace = trans.translateModel(model);

  EXPECT_EQ(1u, workspace.getObjectsByType(IddObjectType::Zone).size());
  EXPECT_EQ(1u, workspace.getObjectsByType(IddObjectType::ZoneList).size());
  EXPECT_EQ(1u, workspace.getObjectsByType(IddObjectType::Lights).size());
}
TEST_F(ModelFixture, DefaultConstructionSet_ShadingSurface)
{
  Model model;

  Point3dVector points;
  points.push_back(Point3d(0,1,0));
  points.push_back(Point3d(0,0,0));
  points.push_back(Point3d(1,0,0));
  ShadingSurface surface(points, model);

  ShadingSurfaceGroup shadingSurfaceGroup(model);
  surface.setShadingSurfaceGroup(shadingSurfaceGroup);

  DefaultConstructionSet defaultConstructionSet(model);
  DefaultSurfaceConstructions defaultSurfaceConstructions(model);
  Construction construction(model);

  EXPECT_TRUE(shadingSurfaceGroup.setShadingSurfaceType("Site"));
  EXPECT_EQ("Site", shadingSurfaceGroup.shadingSurfaceType());

  EXPECT_FALSE(defaultConstructionSet.siteShadingConstruction());
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(surface));
  EXPECT_TRUE(defaultConstructionSet.setSiteShadingConstruction(construction));
  ASSERT_TRUE(defaultConstructionSet.siteShadingConstruction());
  EXPECT_EQ(construction.handle(), defaultConstructionSet.siteShadingConstruction()->handle());
  ASSERT_TRUE(defaultConstructionSet.getDefaultConstruction(surface));
  EXPECT_EQ(construction.handle(), defaultConstructionSet.getDefaultConstruction(surface)->handle());
  defaultConstructionSet.resetSiteShadingConstruction();
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(surface));

  EXPECT_TRUE(shadingSurfaceGroup.setShadingSurfaceType("Building"));
  EXPECT_EQ("Building", shadingSurfaceGroup.shadingSurfaceType());

  EXPECT_FALSE(defaultConstructionSet.buildingShadingConstruction());
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(surface));
  EXPECT_TRUE(defaultConstructionSet.setBuildingShadingConstruction(construction));
  ASSERT_TRUE(defaultConstructionSet.buildingShadingConstruction());
  EXPECT_EQ(construction.handle(), defaultConstructionSet.buildingShadingConstruction()->handle());
  ASSERT_TRUE(defaultConstructionSet.getDefaultConstruction(surface));
  EXPECT_EQ(construction.handle(), defaultConstructionSet.getDefaultConstruction(surface)->handle());
  defaultConstructionSet.resetBuildingShadingConstruction();
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(surface));

  EXPECT_FALSE(shadingSurfaceGroup.setShadingSurfaceType("Space"));
  Space space(model);
  EXPECT_TRUE(shadingSurfaceGroup.setSpace(space));
  EXPECT_EQ("Space", shadingSurfaceGroup.shadingSurfaceType());

  EXPECT_FALSE(defaultConstructionSet.spaceShadingConstruction());
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(surface));
  EXPECT_TRUE(defaultConstructionSet.setSpaceShadingConstruction(construction));
  ASSERT_TRUE(defaultConstructionSet.spaceShadingConstruction());
  EXPECT_EQ(construction.handle(), defaultConstructionSet.spaceShadingConstruction()->handle());
  ASSERT_TRUE(defaultConstructionSet.getDefaultConstruction(surface));
  EXPECT_EQ(construction.handle(), defaultConstructionSet.getDefaultConstruction(surface)->handle());
  defaultConstructionSet.resetSpaceShadingConstruction();
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(surface));
}
Exemple #8
0
 std::vector<Point3d> moveVerticesTowardsPoint(const Point3dVector& vertices, const Point3d& point, double distance)
 {
   Point3dVector result;
   for (const Point3d& vertex : vertices){
     Vector3d vector = point-vertex;
     vector.setLength(distance);
     result.push_back(vertex+vector);
   }
   return result;
 }
TEST_F(ModelFixture, DesignSpecificationOutdoorAir_ThermalZone_2DifferentSpaces)
{
  Model model;

  // 1 m^2
  Point3dVector points;
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(0, 1, 0));
  points.push_back(Point3d(1, 1, 0));
  points.push_back(Point3d(1, 0, 0));
  

  ThermalZone thermalZone(model);

  DesignSpecificationOutdoorAir designSpecificationOutdoorAir1(model);
  EXPECT_TRUE(designSpecificationOutdoorAir1.setOutdoorAirFlowperPerson(0.0));
  EXPECT_TRUE(designSpecificationOutdoorAir1.setOutdoorAirFlowperFloorArea(2.0));

  DesignSpecificationOutdoorAir designSpecificationOutdoorAir2(model);
  EXPECT_TRUE(designSpecificationOutdoorAir2.setOutdoorAirFlowperPerson(3.0));

  Space space1(model);
  EXPECT_TRUE(space1.setThermalZone(thermalZone));
  EXPECT_TRUE(space1.setDesignSpecificationOutdoorAir(designSpecificationOutdoorAir1));
  
  Surface surface1(points, model);
  surface1.setParent(space1);
  EXPECT_EQ(1.0, space1.floorArea());

  space1.setPeoplePerFloorArea(1.0);
  EXPECT_EQ(1.0, space1.numberOfPeople());

  Space space2(model);
  EXPECT_TRUE(space2.setThermalZone(thermalZone));
  EXPECT_TRUE(space2.setDesignSpecificationOutdoorAir(designSpecificationOutdoorAir2));
  
  Surface surface2(points, model);
  surface2.setParent(space2);
  EXPECT_EQ(1.0, space2.floorArea());

  space2.setPeoplePerFloorArea(2.0);
  EXPECT_EQ(2.0, space2.numberOfPeople());

  EXPECT_EQ(2u, model.getModelObjects<DesignSpecificationOutdoorAir>().size());
  boost::optional<Space> combinedSpace = thermalZone.combineSpaces();
  ASSERT_TRUE(combinedSpace);
  EXPECT_FALSE(combinedSpace->isDesignSpecificationOutdoorAirDefaulted());
  ASSERT_TRUE(combinedSpace->designSpecificationOutdoorAir());
  EXPECT_EQ(3u, model.getModelObjects<DesignSpecificationOutdoorAir>().size());
  EXPECT_NE(designSpecificationOutdoorAir1.handle(), combinedSpace->designSpecificationOutdoorAir()->handle());
  EXPECT_NE(designSpecificationOutdoorAir2.handle(), combinedSpace->designSpecificationOutdoorAir()->handle());

  EXPECT_EQ(1.0, combinedSpace->designSpecificationOutdoorAir()->outdoorAirFlowperFloorArea()); // (2*1 + 0*1)/2
  EXPECT_EQ(2.0, combinedSpace->designSpecificationOutdoorAir()->outdoorAirFlowperPerson()); // (0*1 + 3*2)/3
}
TEST_F(ModelFixture, DaylightingDeviceShelf_Throw)
{
  Model model;

  Point3dVector points;
  points.push_back(Point3d(0, 0, 1));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(0, 1, 0));
  points.push_back(Point3d(0, 1, 1));
  SubSurface door(points, model);
  EXPECT_TRUE(door.setSubSurfaceType("Door"));
  EXPECT_EQ("Door", door.subSurfaceType());
  EXPECT_EQ(0, model.getConcreteModelObjects<DaylightingDeviceShelf>().size());

  bool didThrow = false;
  try{
    DaylightingDeviceShelf shelf(door);
  }catch(const openstudio::Exception&){
    didThrow = true;
  }
  EXPECT_TRUE(didThrow);
  EXPECT_EQ(0, model.getConcreteModelObjects<DaylightingDeviceShelf>().size());

  // change to a window
  EXPECT_TRUE(door.setSubSurfaceType("FixedWindow"));
  EXPECT_EQ("FixedWindow", door.subSurfaceType());

  // first one succeeds
  didThrow = false;
  try{
    DaylightingDeviceShelf shelf(door);
  }catch(const openstudio::Exception&){
    didThrow = true;
  }
  EXPECT_FALSE(didThrow);
  EXPECT_EQ(1, model.getConcreteModelObjects<DaylightingDeviceShelf>().size());

  // second call throws
  didThrow = false;
  try{
    DaylightingDeviceShelf shelf(door);
  }catch(const openstudio::Exception&){
    didThrow = true;
  }
  EXPECT_TRUE(didThrow);
  EXPECT_EQ(1, model.getConcreteModelObjects<DaylightingDeviceShelf>().size());

  // changing to door removes light shelf
  EXPECT_TRUE(door.setSubSurfaceType("Door"));
  EXPECT_EQ("Door", door.subSurfaceType());
  EXPECT_FALSE(door.daylightingDeviceShelf());
  EXPECT_FALSE(door.addDaylightingDeviceShelf());
  EXPECT_EQ(0, model.getConcreteModelObjects<DaylightingDeviceShelf>().size());
}
TEST_F(ModelFixture, ShadingSurfaceGroup_Space_Hierarchy)
{
  Model model;

  // add a space
  Space space(model);

  // add a shading surface group
  ShadingSurfaceGroup group(model);
  EXPECT_EQ("Building", group.shadingSurfaceType());
  EXPECT_TRUE(group.setSpace(space));
  EXPECT_EQ("Space", group.shadingSurfaceType());
  ASSERT_TRUE(group.space());
  EXPECT_EQ(space.handle(), group.space()->handle());

  // make a new shading surface
  Point3dVector points;
  points.push_back(Point3d(0, 2, 0));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(1, 0, 0));
  ShadingSurface surface(points, model);
  EXPECT_TRUE(surface.setShadingSurfaceGroup(group));
  ASSERT_TRUE(surface.shadingSurfaceGroup());
  EXPECT_EQ(group.handle(), surface.shadingSurfaceGroup()->handle());

  // check children from group
  ASSERT_EQ(static_cast<unsigned>(1), group.children().size());
  EXPECT_EQ(surface.handle(), group.children()[0].handle());

  // now check children from space
  ASSERT_EQ(static_cast<unsigned>(1), space.children().size());
  EXPECT_EQ(group.handle(), space.children()[0].handle());

  // check parent from group
  ASSERT_TRUE(group.parent());
  EXPECT_EQ(space.handle(), group.parent()->handle());

  // check parent from surface
  ASSERT_TRUE(surface.parent());
  EXPECT_EQ(group.handle(), surface.parent()->handle());

  // clone the space
  ModelObject clone = space.clone(model);
  OptionalSpace spaceClone = clone.optionalCast<Space>();
  ASSERT_TRUE(spaceClone);
  ASSERT_EQ(static_cast<unsigned>(1), spaceClone->children().size());
  EXPECT_NE(group.handle(), spaceClone->children()[0].handle());
  OptionalShadingSurfaceGroup cloneChild = spaceClone->children()[0].optionalCast<ShadingSurfaceGroup>();
  ASSERT_TRUE(cloneChild);
  ASSERT_EQ(static_cast<unsigned>(1), cloneChild->children().size());
  EXPECT_NE(surface.handle(), cloneChild->children()[0].handle());
}
TEST_F(ModelFixture, IlluminanceMap_SpaceSetTransformation)
{
  Model model;
  Space space(model);
  IlluminanceMap map(model);
  map.setXLength(2);
  map.setYLength(2);
  map.setNumberofXGridPoints(2);
  map.setNumberofYGridPoints(2);
  map.setOriginXCoordinate(1);
  map.setOriginYCoordinate(0);
  map.setOriginZCoordinate(2);
  map.setSpace(space);

  Point3dVector testPoints = map.referencePoints();
  ASSERT_EQ(4u, testPoints.size());
  EXPECT_DOUBLE_EQ(0, testPoints[0].x());
  EXPECT_DOUBLE_EQ(0, testPoints[0].y());
  EXPECT_DOUBLE_EQ(0, testPoints[0].z());
  EXPECT_DOUBLE_EQ(2, testPoints[3].x());
  EXPECT_DOUBLE_EQ(2, testPoints[3].y());
  EXPECT_DOUBLE_EQ(0, testPoints[3].z());

  testPoints = space.transformation()*map.transformation()*map.referencePoints();
  EXPECT_DOUBLE_EQ(1, testPoints[0].x());
  EXPECT_DOUBLE_EQ(0, testPoints[0].y());
  EXPECT_DOUBLE_EQ(2, testPoints[0].z());
  EXPECT_DOUBLE_EQ(3, testPoints[3].x());
  EXPECT_DOUBLE_EQ(2, testPoints[3].y());
  EXPECT_DOUBLE_EQ(2, testPoints[3].z());

  EXPECT_TRUE(space.setTransformation(Transformation::translation(Vector3d(1,0,0))));

  testPoints = space.transformation()*map.transformation()*map.referencePoints();
  EXPECT_DOUBLE_EQ(2, testPoints[0].x());
  EXPECT_DOUBLE_EQ(0, testPoints[0].y());
  EXPECT_DOUBLE_EQ(2, testPoints[0].z());
  EXPECT_DOUBLE_EQ(4, testPoints[3].x());
  EXPECT_DOUBLE_EQ(2, testPoints[3].y());
  EXPECT_DOUBLE_EQ(2, testPoints[3].z());

  EXPECT_TRUE(space.setTransformation(Transformation::translation(Vector3d(1,0,0))*Transformation::rotation(Vector3d(0,0,1),-openstudio::degToRad(90))));

  testPoints = space.transformation()*map.transformation()*map.referencePoints();
  EXPECT_DOUBLE_EQ(1, testPoints[0].x());
  EXPECT_DOUBLE_EQ(-1, testPoints[0].y());
  EXPECT_DOUBLE_EQ(2, testPoints[0].z());
  EXPECT_DOUBLE_EQ(3, testPoints[3].x());
  EXPECT_DOUBLE_EQ(-3, testPoints[3].y());
  EXPECT_DOUBLE_EQ(2, testPoints[3].z());
}
TEST_F(ModelFixture, ShadingSurfaceGroup_Hierarchy)
{
  Model model;
  Space space(model);

  ShadingSurfaceGroup siteGroup(model);
  EXPECT_TRUE(siteGroup.setShadingSurfaceType("Site"));

  ShadingSurfaceGroup buildingGroup(model);
  EXPECT_TRUE(buildingGroup.setShadingSurfaceType("Building"));

  ShadingSurfaceGroup spaceGroup(model);
  EXPECT_TRUE(spaceGroup.setSpace(space));

  Point3dVector points;
  points.push_back(Point3d(0, 2, 0));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(1, 0, 0));

  // add site shading surface 
  ShadingSurface siteSurface(points, model);
  EXPECT_TRUE(siteSurface.setShadingSurfaceGroup(siteGroup));
  ASSERT_TRUE(siteSurface.shadingSurfaceGroup());
  EXPECT_EQ(siteGroup.handle(), siteSurface.shadingSurfaceGroup()->handle());

  EXPECT_EQ(1u, siteGroup.shadingSurfaces().size());
  EXPECT_EQ(0u, buildingGroup.shadingSurfaces().size());
  EXPECT_EQ(0u, spaceGroup.shadingSurfaces().size());

  // add building shading surface 
  ShadingSurface buildingSurface(points, model);
  EXPECT_TRUE(buildingSurface.setShadingSurfaceGroup(buildingGroup));
  ASSERT_TRUE(buildingSurface.shadingSurfaceGroup());
  EXPECT_EQ(buildingGroup.handle(), buildingSurface.shadingSurfaceGroup()->handle());

  EXPECT_EQ(1u, siteGroup.shadingSurfaces().size());
  EXPECT_EQ(1u, buildingGroup.shadingSurfaces().size());
  EXPECT_EQ(0u, spaceGroup.shadingSurfaces().size());

   // add space shading surface 
  ShadingSurface spaceSurface(points, model);
  EXPECT_TRUE(spaceSurface.setShadingSurfaceGroup(spaceGroup));
  ASSERT_TRUE(spaceSurface.shadingSurfaceGroup());
  EXPECT_EQ(spaceGroup.handle(), spaceSurface.shadingSurfaceGroup()->handle());

  EXPECT_EQ(1u, siteGroup.shadingSurfaces().size());
  EXPECT_EQ(1u, buildingGroup.shadingSurfaces().size());
  EXPECT_EQ(1u, spaceGroup.shadingSurfaces().size());
}
TEST_F(ModelFixture, InteriorPartitionSurface)
{
  Model model;
 
  Point3dVector points;
  points.push_back(Point3d(0, 1, 0));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(1, 0, 0));
  points.push_back(Point3d(1, 1, 0));

  EXPECT_NO_THROW(InteriorPartitionSurface(points, model));

  InteriorPartitionSurface interiorPartitionSurface(points, model);
  EXPECT_FALSE(interiorPartitionSurface.interiorPartitionSurfaceGroup());
}
TEST_F(ModelFixture, DaylightingDeviceShelf)
{
  Model model;

  // triangle with unit area
  Point3dVector points;
  points.push_back(Point3d(0, 2, 0));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(1, 0, 0));
  SubSurface window(points, model);

  DaylightingDeviceShelf shelf(window);
  EXPECT_EQ(window.handle(), shelf.subSurface().handle());
 
}
TEST_F(ModelFixture, ShadingSurface)
{
  Model model;
 
  Point3dVector points;
  points.push_back(Point3d(0, 1, 0));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(1, 0, 0));
  points.push_back(Point3d(1, 1, 0));

  EXPECT_NO_THROW(ShadingSurface(points, model));

  ShadingSurface shadingSurface(points, model);
  EXPECT_FALSE(shadingSurface.shadingSurfaceGroup());
}
TEST_F(EnergyPlusFixture,ForwardTranslator_Surface_DefaultConstruction)
{
  Model model;

  Construction construction(model);

  DefaultSurfaceConstructions defaultSurfaceConstructions(model);
  defaultSurfaceConstructions.setRoofCeilingConstruction(construction);

  DefaultConstructionSet defaultConstructionSet(model);
  defaultConstructionSet.setDefaultExteriorSurfaceConstructions(defaultSurfaceConstructions);

  Building building = model.getUniqueModelObject<Building>();
  building.setDefaultConstructionSet(defaultConstructionSet);

  Space space(model);
  ThermalZone zone(model);
  EXPECT_TRUE(space.setThermalZone(zone));  

  Point3dVector points;
  points.push_back(Point3d(0, 1, 0));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(1, 0, 0));
  points.push_back(Point3d(1, 1, 0));
  Surface surface(points, model);
  surface.setSpace(space);

  EXPECT_EQ("RoofCeiling", surface.surfaceType());
  EXPECT_EQ("Outdoors", surface.outsideBoundaryCondition());
  EXPECT_FALSE(surface.adjacentSurface());
  ASSERT_TRUE(surface.construction());
  EXPECT_TRUE(surface.isConstructionDefaulted());
  EXPECT_EQ(construction.handle(), surface.construction()->handle());

  ForwardTranslator forwardTranslator;
  Workspace workspace = forwardTranslator.translateModel(model);
  EXPECT_EQ(0u, forwardTranslator.errors().size());
  EXPECT_EQ(0u, forwardTranslator.warnings().size());

  ASSERT_EQ(1u, workspace.getObjectsByType(IddObjectType::BuildingSurface_Detailed).size());
  ASSERT_EQ(1u, workspace.getObjectsByType(IddObjectType::Construction).size());

  WorkspaceObject surfaceObject = workspace.getObjectsByType(IddObjectType::BuildingSurface_Detailed)[0];
  WorkspaceObject constructionObject = workspace.getObjectsByType(IddObjectType::Construction)[0];

  ASSERT_TRUE(surfaceObject.getTarget(BuildingSurface_DetailedFields::ConstructionName));
  EXPECT_EQ(constructionObject.handle(), surfaceObject.getTarget(BuildingSurface_DetailedFields::ConstructionName)->handle());
}
TEST_F(ModelFixture, DefaultConstructionSet_ExteriorSubSurfaces)
{
  Model model;

  Point3dVector points;
  points.push_back(Point3d(0,1,0));
  points.push_back(Point3d(0,0,0));
  points.push_back(Point3d(1,0,0));
  Surface surface(points, model);
  EXPECT_TRUE(surface.setOutsideBoundaryCondition("Outdoors"));

  SubSurface subSurface(points, model);
  EXPECT_TRUE(subSurface.setSurface(surface));

  DefaultConstructionSet defaultConstructionSet(model);
  DefaultSubSurfaceConstructions defaultSubSurfaceConstructions(model);
  Construction construction(model);

  EXPECT_FALSE(defaultConstructionSet.defaultExteriorSubSurfaceConstructions());
  EXPECT_TRUE(defaultConstructionSet.setDefaultExteriorSubSurfaceConstructions(defaultSubSurfaceConstructions));
  ASSERT_TRUE(defaultConstructionSet.defaultExteriorSubSurfaceConstructions());
  EXPECT_EQ(defaultSubSurfaceConstructions.handle(), defaultConstructionSet.defaultExteriorSubSurfaceConstructions()->handle());

  EXPECT_TRUE(subSurface.setSubSurfaceType("FixedWindow"));
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(subSurface));
  EXPECT_TRUE(defaultSubSurfaceConstructions.setFixedWindowConstruction(construction));
  ASSERT_TRUE(defaultConstructionSet.getDefaultConstruction(subSurface));
  EXPECT_EQ(construction.handle(), defaultConstructionSet.getDefaultConstruction(subSurface)->handle());
  defaultSubSurfaceConstructions.resetFixedWindowConstruction();
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(subSurface));

  EXPECT_TRUE(subSurface.setSubSurfaceType("Door"));
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(subSurface));
  EXPECT_TRUE(defaultSubSurfaceConstructions.setDoorConstruction(construction));
  ASSERT_TRUE(defaultConstructionSet.getDefaultConstruction(subSurface));
  EXPECT_EQ(construction.handle(), defaultConstructionSet.getDefaultConstruction(subSurface)->handle());
  defaultSubSurfaceConstructions.resetDoorConstruction();
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(subSurface));

  EXPECT_TRUE(subSurface.setSubSurfaceType("Skylight"));
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(subSurface));
  EXPECT_TRUE(defaultSubSurfaceConstructions.setSkylightConstruction(construction));
  ASSERT_TRUE(defaultConstructionSet.getDefaultConstruction(subSurface));
  EXPECT_EQ(construction.handle(), defaultConstructionSet.getDefaultConstruction(subSurface)->handle());
  defaultSubSurfaceConstructions.resetSkylightConstruction();
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(subSurface));
}
TEST_F(ModelFixture, ModelObject_Clone_DifferentModel) {
  // Make model object with resource that has children
  Model original;
  Point3dVector points;
  points.push_back(Point3d(0, 1, 0));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(1, 0, 0));
  Surface surface(points, original);
  Construction construction(original);
  surface.setConstruction(construction);
  construction.standardsInformation(); // creates object
  StandardOpaqueMaterial material(original);
  construction.setLayers(MaterialVector(1u,material));
  EXPECT_EQ(4u,original.numObjects());

  // Clone into new model -- everything added
  Model newModel;
  EXPECT_EQ(0u,newModel.numObjects());
  Surface newSurface = surface.clone(newModel).cast<Surface>();
  EXPECT_EQ(4u,newModel.numObjects());
  EXPECT_TRUE(newModel.isMember(newSurface.handle()));

  // Clone into that model again -- object added, resource and children reused
  Surface anotherNewSurface = surface.clone(newModel).cast<Surface>();
  EXPECT_FALSE(anotherNewSurface == newSurface);
  EXPECT_EQ(5u,newModel.numObjects());
  ASSERT_TRUE(anotherNewSurface.construction());
  ASSERT_TRUE(newSurface.construction());
  EXPECT_TRUE(anotherNewSurface.construction().get() == newSurface.construction().get());
  EXPECT_TRUE(anotherNewSurface.construction().get().standardsInformation() == newSurface.construction().get().standardsInformation());
  EXPECT_TRUE(anotherNewSurface.construction().get().cast<LayeredConstruction>().layers() == newSurface.construction().get().cast<LayeredConstruction>().layers());

  // Change the data in the resource's child
  StandardsInformationConstructionVector stdsInfos = newModel.getModelObjects<StandardsInformationConstruction>();
  EXPECT_EQ(1u,stdsInfos.size());
  stdsInfos[0].setIntendedSurfaceType(StandardsInformationConstruction::intendedSurfaceTypeValues()[0]);

  // Clone into that model again -- everything added, except resource of resource
  anotherNewSurface = surface.clone(newModel).cast<Surface>();
  EXPECT_FALSE(anotherNewSurface == newSurface);
  EXPECT_EQ(8u,newModel.numObjects());
  ASSERT_TRUE(anotherNewSurface.construction());
  ASSERT_TRUE(newSurface.construction());
  EXPECT_FALSE(anotherNewSurface.construction().get() == newSurface.construction().get());
  EXPECT_FALSE(anotherNewSurface.construction().get().standardsInformation() == newSurface.construction().get().standardsInformation());
  EXPECT_TRUE(anotherNewSurface.construction().get().cast<LayeredConstruction>().layers() == newSurface.construction().get().cast<LayeredConstruction>().layers());
}
TEST_F(ModelFixture, ElectricEquipment_Cost) {
  Model model;
  Building building = model.getUniqueModelObject<Building>();
  SpaceType spaceType(model);

  Point3dVector floorPrint;
  floorPrint.push_back(Point3d(0, 10, 0));
  floorPrint.push_back(Point3d(10, 10, 0));
  floorPrint.push_back(Point3d(10, 0, 0));
  floorPrint.push_back(Point3d(0, 0, 0));

  boost::optional<Space> space1 = Space::fromFloorPrint(floorPrint, 3, model);
  ASSERT_TRUE(space1);
  boost::optional<Space> space2 = Space::fromFloorPrint(floorPrint, 3, model);
  ASSERT_TRUE(space2);

  EXPECT_DOUBLE_EQ(200, building.floorArea());

  ElectricEquipmentDefinition definition(model);
  ElectricEquipment electricEquipment1(definition);
  ElectricEquipment electricEquipment2(definition);

  boost::optional<LifeCycleCost> cost = LifeCycleCost::createLifeCycleCost("Dusting", definition, 0.5, "CostPerArea", "Maintenance", 1);
  ASSERT_TRUE(cost);
  EXPECT_EQ(1, cost->repeatPeriodYears());

  EXPECT_DOUBLE_EQ(0, cost->totalCost());

  electricEquipment1.setSpace(*space1);
  
  EXPECT_DOUBLE_EQ(50, cost->totalCost());

  electricEquipment2.setSpace(*space2);

  EXPECT_DOUBLE_EQ(100, cost->totalCost());
  
  ThermalZone thermalZone(model);
  space1->setThermalZone(thermalZone);
  thermalZone.setMultiplier(4);

  EXPECT_DOUBLE_EQ(250.0, cost->totalCost());

  building.setSpaceType(spaceType);
  electricEquipment1.setSpaceType(spaceType);

  EXPECT_DOUBLE_EQ(300.0, cost->totalCost());
}
TEST_F(ModelFixture, InteriorPartitionSurface_Hierarchy)
{
  Model model;

  Space space(model);

  // add a interior partition surface group
  InteriorPartitionSurfaceGroup group(model);
  EXPECT_FALSE(group.space());
  EXPECT_TRUE(group.setSpace(space));
  ASSERT_TRUE(group.space());
  EXPECT_EQ(space.handle(), group.space()->handle());

  // make a new interior partition surface
  Point3dVector points;
  points.push_back(Point3d(0, 2, 0));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(1, 0, 0));
  InteriorPartitionSurface surface(points, model);
  EXPECT_FALSE(surface.interiorPartitionSurfaceGroup());
  EXPECT_TRUE(surface.setInteriorPartitionSurfaceGroup(group));
  ASSERT_TRUE(surface.interiorPartitionSurfaceGroup());
  EXPECT_EQ(group.handle(), surface.interiorPartitionSurfaceGroup()->handle());

  // check children from group
  ASSERT_EQ(static_cast<unsigned>(1), group.children().size());
  EXPECT_EQ(surface.handle(), group.children()[0].handle());

  // now check children from space
  ASSERT_EQ(static_cast<unsigned>(1), space.children().size());
  EXPECT_EQ(group.handle(), space.children()[0].handle());

  // check parent from group
  ASSERT_TRUE(group.parent());
  EXPECT_EQ(space.handle(), group.parent()->handle());

  // check parent from surface
  ASSERT_TRUE(surface.parent());
  EXPECT_EQ(group.handle(), surface.parent()->handle());

  // clone the space
  ModelObject clone = space.clone(model);
  OptionalSpace spaceClone = clone.optionalCast<Space>();
  ASSERT_TRUE(spaceClone);
  ASSERT_EQ(static_cast<unsigned>(1), spaceClone->children().size());
  EXPECT_NE(group.handle(), spaceClone->children()[0].handle());
}
Exemple #22
0
    /// get the vertices
    Point3dVector PlanarSurface_Impl::vertices() const
    {
      if (!m_cachedVertices){
        Point3dVector result;

        BOOST_FOREACH(const ModelExtensibleGroup& group,castVector<ModelExtensibleGroup>(extensibleGroups()))
        {
          OptionalDouble x = group.getDouble(0);
          OptionalDouble y = group.getDouble(1);
          OptionalDouble z = group.getDouble(2);

          if (x && y && z){
            result.push_back(Point3d(*x, *y, *z));
          }else{
            LOG(Error, "Could not read vertex " << group.groupIndex() << " in " << briefDescription() << "." );
          }
        }
TEST_F(ModelFixture, Construction_NetArea_SubSurface) {
  Model model;

  ThermalZone thermalZone(model);

  Space space(model);
  space.setThermalZone(thermalZone);

  Construction construction1(model);
  Construction construction2(model);
  EXPECT_DOUBLE_EQ(0.0, construction1.getNetArea());
  EXPECT_DOUBLE_EQ(0.0, construction2.getNetArea());

  Point3dVector points;
  points.push_back(Point3d(0, 0, 10));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(0, 10, 0));
  points.push_back(Point3d(0, 10, 10));

  Surface surface(points, model);
  surface.setConstruction(construction1);
  surface.setSpace(space);
  EXPECT_EQ("Wall", surface.surfaceType());
  EXPECT_DOUBLE_EQ(100.0, surface.netArea());
  EXPECT_DOUBLE_EQ(100.0, construction1.getNetArea());
  EXPECT_DOUBLE_EQ(0.0, construction2.getNetArea());
  EXPECT_DOUBLE_EQ(0, surface.windowToWallRatio());

  points.clear();
  points.push_back(Point3d(0, 0, 2));
  points.push_back(Point3d(0, 0, 1));
  points.push_back(Point3d(0, 1, 1));
  points.push_back(Point3d(0, 1, 2));

  SubSurface subSurface(points, model);
  subSurface.setConstruction(construction2);
  subSurface.setSurface(surface);
  EXPECT_EQ("FixedWindow", subSurface.subSurfaceType());
  EXPECT_DOUBLE_EQ(1.0, subSurface.netArea());
  EXPECT_DOUBLE_EQ(99.0, construction1.getNetArea());
  EXPECT_DOUBLE_EQ(1.0, construction2.getNetArea());
  EXPECT_DOUBLE_EQ(1.0/100.0, surface.windowToWallRatio());

  EXPECT_TRUE(subSurface.setMultiplier(4));
  EXPECT_DOUBLE_EQ(1.0, subSurface.netArea());
  EXPECT_DOUBLE_EQ(96.0, construction1.getNetArea());
  EXPECT_DOUBLE_EQ(4.0, construction2.getNetArea());
  EXPECT_DOUBLE_EQ(4.0/100.0, surface.windowToWallRatio());

  EXPECT_TRUE(thermalZone.setMultiplier(4));
  EXPECT_DOUBLE_EQ(1.0, subSurface.netArea());
  EXPECT_DOUBLE_EQ(4*96.0, construction1.getNetArea());
  EXPECT_DOUBLE_EQ(4*4.0, construction2.getNetArea());
  EXPECT_DOUBLE_EQ(4.0/100.0, surface.windowToWallRatio());
}
TEST_F(EnergyPlusFixture,ForwardTranslator_Surface)
{
  Model model;
  
  Point3dVector points;
  points.push_back(Point3d(0, 1, 0));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(1, 0, 0));
  points.push_back(Point3d(1, 1, 0));
  Surface surface(points, model);

  ForwardTranslator forwardTranslator;
  Workspace workspace = forwardTranslator.translateModel(model);
  EXPECT_EQ(0u, forwardTranslator.errors().size());
  EXPECT_EQ(0u, forwardTranslator.warnings().size());

  ASSERT_EQ(1u, workspace.getObjectsByType(IddObjectType::BuildingSurface_Detailed).size());
}
TEST_F(ModelFixture, DefaultConstructionSet_GroundContactSurfaces)
{
  Model model;

  Point3dVector points;
  points.push_back(Point3d(0,1,0));
  points.push_back(Point3d(0,0,0));
  points.push_back(Point3d(1,0,0));
  Surface surface(points, model);
  EXPECT_TRUE(surface.setOutsideBoundaryCondition("Ground"));

  DefaultConstructionSet defaultConstructionSet(model);
  DefaultSurfaceConstructions defaultSurfaceConstructions(model);
  Construction construction(model);

  EXPECT_FALSE(defaultConstructionSet.defaultGroundContactSurfaceConstructions());
  EXPECT_TRUE(defaultConstructionSet.setDefaultGroundContactSurfaceConstructions(defaultSurfaceConstructions));
  ASSERT_TRUE(defaultConstructionSet.defaultGroundContactSurfaceConstructions());
  EXPECT_EQ(defaultSurfaceConstructions.handle(), defaultConstructionSet.defaultGroundContactSurfaceConstructions()->handle());

  EXPECT_TRUE(surface.setSurfaceType("Floor"));
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(surface));
  EXPECT_TRUE(defaultSurfaceConstructions.setFloorConstruction(construction));
  ASSERT_TRUE(defaultConstructionSet.getDefaultConstruction(surface));
  EXPECT_EQ(construction.handle(), defaultConstructionSet.getDefaultConstruction(surface)->handle());
  defaultSurfaceConstructions.resetFloorConstruction();
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(surface));

  EXPECT_TRUE(surface.setSurfaceType("Wall"));
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(surface));
  EXPECT_TRUE(defaultSurfaceConstructions.setWallConstruction(construction));
  ASSERT_TRUE(defaultConstructionSet.getDefaultConstruction(surface));
  EXPECT_EQ(construction.handle(), defaultConstructionSet.getDefaultConstruction(surface)->handle());
  defaultSurfaceConstructions.resetWallConstruction();
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(surface));

  EXPECT_TRUE(surface.setSurfaceType("RoofCeiling"));
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(surface));
  EXPECT_TRUE(defaultSurfaceConstructions.setRoofCeilingConstruction(construction));
  ASSERT_TRUE(defaultConstructionSet.getDefaultConstruction(surface));
  EXPECT_EQ(construction.handle(), defaultConstructionSet.getDefaultConstruction(surface)->handle());
  defaultSurfaceConstructions.resetRoofCeilingConstruction();
  EXPECT_FALSE(defaultConstructionSet.getDefaultConstruction(surface));
}
TEST_F(EnergyPlusFixture,ForwardTranslator_ThermalZone_OneZone_TwoSpaces_DifferentSpaceType)
{
  Model model;

  Point3dVector points;
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(0, 1, 0));
  points.push_back(Point3d(1, 1, 0));
  points.push_back(Point3d(1, 0, 0));

  SpaceType spaceType1(model);
  spaceType1.setLightingPowerPerFloorArea(1);

  SpaceType spaceType2(model);
  spaceType2.setLightingPowerPerFloorArea(2);

  ThermalZone zone(model);

  Space space1(model);
  space1.setThermalZone(zone);
  space1.setSpaceType(spaceType1);

  Space space2(model);
  space2.setThermalZone(zone);
  space2.setSpaceType(spaceType2);

  Surface surface1(points, model);
  surface1.setSpace(space1);

  Surface surface2(points, model);
  surface2.setSpace(space2);

  EXPECT_EQ(1, space1.floorArea());
  EXPECT_EQ(1, space2.floorArea());
  EXPECT_EQ(1, space1.lightingPowerPerFloorArea());
  EXPECT_EQ(2, space2.lightingPowerPerFloorArea());

  ForwardTranslator trans;
  Workspace workspace = trans.translateModel(model);

  EXPECT_EQ(1u, workspace.getObjectsByType(IddObjectType::Zone).size());
  EXPECT_EQ(0u, workspace.getObjectsByType(IddObjectType::ZoneList).size());
  EXPECT_EQ(2u, workspace.getObjectsByType(IddObjectType::Lights).size());
}
Exemple #27
0
  /// compute centroid from surface as Point3dVector
  OptionalPoint3d getCentroid(const Point3dVector& points)
  {
    OptionalPoint3d result;

    if (points.size() >= 3){
      // convert to face coordinates
      Transformation alignFace = Transformation::alignFace(points);
      Point3dVector surfacePoints = alignFace.inverse()*points;

      unsigned N = surfacePoints.size();
      double A = 0;
      double cx = 0;
      double cy = 0;
      for (unsigned i = 0; i < N; ++i){
        double x1, x2, y1, y2;
        if (i == N-1){
          x1 = surfacePoints[i].x();
          x2 = surfacePoints[0].x();
          y1 = surfacePoints[i].y();
          y2 = surfacePoints[0].y();
        }else{
          x1 = surfacePoints[i].x();
          x2 = surfacePoints[i+1].x();
          y1 = surfacePoints[i].y();
          y2 = surfacePoints[i+1].y();
        }

        double dA = (x1*y2-x2*y1);
        A += 0.5*dA;
        cx += (x1+x2)*dA;
        cy += (y1+y2)*dA;
      }

      if (A > 0){
        // centroid in face coordinates
        Point3d surfaceCentroid(cx/(6.0*A), cy/(6.0*A), 0.0);

        // centroid
        result = alignFace*surfaceCentroid;
      }
    }
    return result;
  }
Exemple #28
0
TEST_F(ModelFixture, Lights_FloorArea) {
  Model model;
  Building building = model.getUniqueModelObject<Building>();
  SpaceType spaceType(model);
  building.setSpaceType(spaceType);

  Point3dVector floorPrint;
  floorPrint.push_back(Point3d(0, 10, 0));
  floorPrint.push_back(Point3d(10, 10, 0));
  floorPrint.push_back(Point3d(10, 0, 0));
  floorPrint.push_back(Point3d(0, 0, 0));

  boost::optional<Space> space1 = Space::fromFloorPrint(floorPrint, 3, model);
  ASSERT_TRUE(space1);
  boost::optional<Space> space2 = Space::fromFloorPrint(floorPrint, 3, model);
  ASSERT_TRUE(space2);

  LightsDefinition definition(model);
  Lights lights(definition);
  lights.setSpace(*space1);

  EXPECT_DOUBLE_EQ(200, building.floorArea());
  EXPECT_DOUBLE_EQ(100, lights.floorArea());
  EXPECT_DOUBLE_EQ(100, definition.floorArea());

  lights.setSpaceType(spaceType);
  EXPECT_DOUBLE_EQ(200, building.floorArea());
  EXPECT_DOUBLE_EQ(200, lights.floorArea());
  EXPECT_DOUBLE_EQ(200, definition.floorArea());

  ThermalZone thermalZone(model);
  space1->setThermalZone(thermalZone);
  thermalZone.setMultiplier(2);

  EXPECT_DOUBLE_EQ(300, building.floorArea());
  EXPECT_DOUBLE_EQ(300, lights.floorArea());
  EXPECT_DOUBLE_EQ(300, definition.floorArea());

  lights.setSpace(*space1);
  EXPECT_DOUBLE_EQ(300, building.floorArea());
  EXPECT_DOUBLE_EQ(200, lights.floorArea());
  EXPECT_DOUBLE_EQ(200, definition.floorArea());
}
TEST_F(EnergyPlusFixture,ForwardTranslator_ShadingSurface_Building)
{
  Model model;
  ShadingSurfaceGroup shadingSurfaceGroup(model);
  EXPECT_TRUE(shadingSurfaceGroup.setShadingSurfaceType("Building"));

  Point3dVector points;
  points.push_back(Point3d(0,1,0));
  points.push_back(Point3d(1,1,0));
  points.push_back(Point3d(1,0,0));
  points.push_back(Point3d(0,0,0));
    
  ShadingSurface shadingSurface(points, model);
  EXPECT_TRUE(shadingSurface.setShadingSurfaceGroup(shadingSurfaceGroup));

  ForwardTranslator forwardTranslator;
  Workspace workspace = forwardTranslator.translateModel(model);
  
  EXPECT_EQ(1u, workspace.getObjectsByType(IddObjectType::Shading_Building_Detailed).size());
}
TEST_F(ModelFixture, DaylightingDeviceShelf)
{
  Model model;

  Point3dVector points;
  points.push_back(Point3d(0, 0, 1));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(0, 1, 0));
  points.push_back(Point3d(0, 1, 1));
  SubSurface window(points, model);
  EXPECT_EQ("FixedWindow", window.subSurfaceType());

  EXPECT_FALSE(window.daylightingDeviceShelf());

  DaylightingDeviceShelf shelf(window);
  UUID shelfHandle = shelf.handle();
  ASSERT_TRUE(window.daylightingDeviceShelf());
  EXPECT_EQ(shelfHandle, window.daylightingDeviceShelf()->handle());
  ASSERT_TRUE(window.addDaylightingDeviceShelf());
  EXPECT_EQ(shelfHandle, window.addDaylightingDeviceShelf()->handle());
  EXPECT_EQ(window.addDaylightingDeviceShelf()->handle(), window.daylightingDeviceShelf()->handle());
  EXPECT_EQ(window.handle(), shelf.subSurface().handle());

  shelf.remove();
  EXPECT_FALSE(window.daylightingDeviceShelf());
  ASSERT_TRUE(window.addDaylightingDeviceShelf());
  shelfHandle = window.addDaylightingDeviceShelf()->handle();
  ASSERT_TRUE(window.addDaylightingDeviceShelf());
  EXPECT_EQ(shelfHandle, window.addDaylightingDeviceShelf()->handle());
  ASSERT_TRUE(window.addDaylightingDeviceShelf());
  EXPECT_EQ(shelfHandle, window.addDaylightingDeviceShelf()->handle());
  ASSERT_TRUE(window.daylightingDeviceShelf());
  EXPECT_EQ(shelfHandle, window.daylightingDeviceShelf()->handle());

  // changing to door removes light shelf
  EXPECT_TRUE(window.setSubSurfaceType("Door"));
  EXPECT_EQ("Door", window.subSurfaceType());
  EXPECT_FALSE(window.daylightingDeviceShelf());
  EXPECT_FALSE(window.addDaylightingDeviceShelf());
}