Question-and-Answer Resource for the Building Energy Modeling Community
Get started with the Help page
Ask Your Question

Revision history [back]

The algorithm is defined in the source code here:

https://github.com/NREL/OpenStudio/blob/69090ca07a98bdc588958c1f17cc17e6976ce007/openstudiocore/src/model/SubSurface.cpp#L970-#L1023

  boost::optional<ShadingSurface> SubSurface_Impl::addOverhangByProjectionFactor(double projectionFactor, double offsetFraction)
  {
    std::string subSurfaceType = this->subSurfaceType();
    if (!(istringEqual("FixedWindow", subSurfaceType) ||
          istringEqual("OperableWindow", subSurfaceType) ||
          istringEqual("GlassDoor", subSurfaceType))){
      return boost::none;
    }

    Model model = this->model();
    boost::optional<Space> space = this->space();
    boost::optional<ShadingSurface> shadingSurface;
    if (space){

      Point3dVector vertices = this->vertices();
      Transformation transformation = Transformation::alignFace(vertices);
      Point3dVector faceVertices = transformation.inverse() * vertices;

      // new coordinate system has z' in direction of outward normal, y' is up
      double xmin = std::numeric_limits<double>::max();
      double xmax = std::numeric_limits<double>::min();
      double ymin = std::numeric_limits<double>::max();
      double ymax = std::numeric_limits<double>::min();
      for (const Point3d& faceVertex : faceVertices){
        xmin = std::min(xmin, faceVertex.x());
        xmax = std::max(xmax, faceVertex.x());
        ymin = std::min(ymin, faceVertex.y());
        ymax = std::max(ymax, faceVertex.y());
      }
      if ((xmin > xmax) || (ymin > ymax)){
        return boost::none;
      }

      double offset = offsetFraction*(ymax-ymin);
      double depth = projectionFactor*(offset + (ymax-ymin));

      Point3dVector overhangVertices;
      overhangVertices.push_back(Point3d(xmax + offset, ymax + offset, 0));
      overhangVertices.push_back(Point3d(xmin - offset, ymax + offset, 0));
      overhangVertices.push_back(Point3d(xmin - offset, ymax + offset, depth));
      overhangVertices.push_back(Point3d(xmax + offset, ymax + offset, depth));

      ShadingSurfaceGroup shadingSurfaceGroup(model);
      shadingSurfaceGroup.setName(this->name().get() + " Shading Surfaces");
      shadingSurfaceGroup.setSpace(*space);

      shadingSurface = ShadingSurface(transformation*overhangVertices, model);
      shadingSurface->setShadingSurfaceGroup(shadingSurfaceGroup);

      shadingSurfaceGroup.setShadedSubSurface(getObject<SubSurface>());
    }

    return shadingSurface;
}

Basically, it sizes the window in proportion to window height. Notice that in addition to adjusting shading depth it will increase or decrease the width of the shading device so it may not cover the whole window.

I found that frustrating, so I made a script to add exterior shading to windows which gives a lot mores specific options for adjusting dimensions of shading devices. It's available with other SketchUp userscripts on the Unmet Hours Github repo.