| 1048 | } |
| 1049 | |
| 1050 | boost::optional<ShadingSurface> SubSurface_Impl::addOverhangByProjectionFactor(double projectionFactor, double offsetFraction) { |
| 1051 | std::string subSurfaceType = this->subSurfaceType(); |
| 1052 | if (!(istringEqual("FixedWindow", subSurfaceType) || istringEqual("OperableWindow", subSurfaceType) |
| 1053 | || istringEqual("GlassDoor", subSurfaceType))) { |
| 1054 | return boost::none; |
| 1055 | } |
| 1056 | |
| 1057 | Model model = this->model(); |
| 1058 | boost::optional<Space> space = this->space(); |
| 1059 | boost::optional<ShadingSurface> shadingSurface; |
| 1060 | if (space) { |
| 1061 | |
| 1062 | Point3dVector vertices = this->vertices(); |
| 1063 | Transformation transformation = Transformation::alignFace(vertices); |
| 1064 | Point3dVector faceVertices = transformation.inverse() * vertices; |
| 1065 | |
| 1066 | // new coordinate system has z' in direction of outward normal, y' is up |
| 1067 | double xmin = std::numeric_limits<double>::max(); |
| 1068 | double xmax = std::numeric_limits<double>::min(); |
| 1069 | double ymin = std::numeric_limits<double>::max(); |
| 1070 | double ymax = std::numeric_limits<double>::min(); |
| 1071 | for (const Point3d& faceVertex : faceVertices) { |
| 1072 | xmin = std::min(xmin, faceVertex.x()); |
| 1073 | xmax = std::max(xmax, faceVertex.x()); |
| 1074 | ymin = std::min(ymin, faceVertex.y()); |
| 1075 | ymax = std::max(ymax, faceVertex.y()); |
| 1076 | } |
| 1077 | if ((xmin > xmax) || (ymin > ymax)) { |
| 1078 | return boost::none; |
| 1079 | } |
| 1080 | |
| 1081 | double offset = offsetFraction * (ymax - ymin); |
| 1082 | double depth = projectionFactor * (offset + (ymax - ymin)); |
| 1083 | |
| 1084 | Point3dVector overhangVertices{ |
| 1085 | {xmax + offset, ymax + offset, 0}, |
| 1086 | {xmin - offset, ymax + offset, 0}, |
| 1087 | {xmin - offset, ymax + offset, depth}, |
| 1088 | {xmax + offset, ymax + offset, depth}, |
| 1089 | }; |
| 1090 | |
| 1091 | ShadingSurfaceGroup shadingSurfaceGroup(model); |
| 1092 | shadingSurfaceGroup.setName(this->name().get() + " Shading Surfaces"); |
| 1093 | shadingSurfaceGroup.setSpace(*space); |
| 1094 | |
| 1095 | shadingSurface = ShadingSurface(transformation * overhangVertices, model); |
| 1096 | shadingSurface->setShadingSurfaceGroup(shadingSurfaceGroup); |
| 1097 | |
| 1098 | shadingSurfaceGroup.setShadedSubSurface(getObject<SubSurface>()); |
| 1099 | } |
| 1100 | |
| 1101 | return shadingSurface; |
| 1102 | } |
| 1103 | |
| 1104 | std::vector<ShadingSurfaceGroup> SubSurface_Impl::shadingSurfaceGroups() const { |
| 1105 | return getObject<ModelObject>().getModelObjectSources<ShadingSurfaceGroup>(ShadingSurfaceGroup::iddObjectType()); |
no test coverage detected