Skip to content

Commit 851d1ac

Browse files
author
Fraser Greenroyd
authored
Environment_Engine: Added ElementsInSpace and dependant IsContaining methods / optimisations (#3195)
2 parents 32cd615 + ef6f299 commit 851d1ac

File tree

3 files changed

+238
-28
lines changed

3 files changed

+238
-28
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* This file is part of the Buildings and Habitats object Model (BHoM)
3+
* Copyright (c) 2015 - 2023, the respective contributors. All rights reserved.
4+
*
5+
* Each contributor holds copyright over their respective contributions.
6+
* The project versioning (Git) records all such contribution source information.
7+
*
8+
*
9+
* The BHoM is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License as published by
11+
* the Free Software Foundation, either version 3.0 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* The BHoM is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU Lesser General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public License
20+
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
21+
*/
22+
23+
using System;
24+
using System.Collections.Generic;
25+
using System.Linq;
26+
using System.Text;
27+
using System.Threading.Tasks;
28+
29+
using BH.oM.Environment.Elements;
30+
using BH.oM.Architecture.Elements;
31+
32+
using BH.Engine.Geometry;
33+
using BH.oM.Geometry;
34+
35+
using BH.oM.Base.Attributes;
36+
using System.ComponentModel;
37+
38+
using BH.oM.Analytical.Elements;
39+
using BH.oM.Dimensional;
40+
41+
namespace BH.Engine.Environment
42+
{
43+
public static partial class Compute
44+
{
45+
[Description("Gets the elements that lie within the provided space.")]
46+
[Input("space", "An Environment Space object defining a perimeter to build a 3D volume from and check if the volume contains the provided point.")]
47+
[Input("spaceHeight", "The height of the space.", typeof(BH.oM.Quantities.Attributes.Length))]
48+
[Input("elements", "The elements being checked to see if they are contained within the bounds of the 3D volume.")]
49+
[Input("acceptOnEdges", "Decide whether to allow elements which sit on the edge of the space, default false.")]
50+
[Input("acceptPartial", "Decide whether to include elements only partially within the space, default false.")]
51+
[Output("elements", "The elements from the provided elements that are within the space.")]
52+
public static List<IElement> ElementsInSpace(this Space space, double spaceHeight, List<IElement> elements, bool acceptOnEdges = false, bool acceptPartial = false)
53+
{
54+
if (space == null)
55+
return new List<IElement>();
56+
57+
List<bool> isContaining = space.IsContaining(spaceHeight, elements, acceptOnEdges, acceptPartial);
58+
59+
return elements
60+
.Zip(isContaining, (elem, inSpace) => new {
61+
elem,
62+
inSpace,
63+
})
64+
.Where(item => item.inSpace)
65+
.Select(item => item.elem)
66+
.ToList();
67+
}
68+
}
69+
}

Environment_Engine/Query/IsContaining.cs

Lines changed: 116 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,16 @@
2020
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
2121
*/
2222

23-
using System;
24-
using System.Collections.Generic;
25-
using System.Linq;
26-
using System.Text;
27-
using System.Threading.Tasks;
28-
29-
using BH.oM.Environment;
30-
using BH.oM.Environment.Elements;
31-
using BH.oM.Base;
32-
33-
using BH.oM.Geometry;
3423
using BH.Engine.Geometry;
35-
24+
using BH.Engine.Spatial;
3625
using BH.oM.Base.Attributes;
26+
using BH.oM.Dimensional;
27+
using BH.oM.Environment.Elements;
28+
using BH.oM.Geometry;
29+
using System;
30+
using System.Collections.Generic;
3731
using System.ComponentModel;
32+
using System.Linq;
3833

3934
namespace BH.Engine.Environment
4035
{
@@ -88,16 +83,33 @@ public static bool IsContaining(this Panel panel, Point pt, bool acceptOnEdges =
8883
[Output("isContaining", "True if the point is contained within the bounds of the panels, false if it is not")]
8984
public static bool IsContaining(this List<Panel> panels, Point point, bool acceptOnEdges = false, double tolerance = BH.oM.Geometry.Tolerance.Distance)
9085
{
91-
if(panels == null)
86+
if (panels == null)
9287
{
9388
BH.Engine.Base.Compute.RecordError("Cannot query if a collection of panels contains a point if the panels are null.");
9489
return false;
9590
}
9691

97-
if(point == null)
92+
List<Plane> planes = new List<Plane>();
93+
foreach (Panel be in panels)
94+
planes.Add(be.Polyline().IControlPoints().FitPlane(tolerance));
95+
96+
List<Point> ctrPoints = panels.SelectMany(x => x.Polyline().IControlPoints()).ToList();
97+
BoundingBox boundingBox = BH.Engine.Geometry.Query.Bounds(ctrPoints);
98+
99+
return IsContaining(panels, planes, boundingBox, point, acceptOnEdges);
100+
}
101+
102+
[Description("Defines whether a collection of Environment Panels contains each of a provided list of points.")]
103+
[Input("panels", "A collection of Environment Panels to check with.")]
104+
[Input("points", "The points to check to see if each point is contained within the bounds of the panels.")]
105+
[Input("acceptOnEdges", "Decide whether to allow the point to sit on the edge of the panel, default false.")]
106+
[Output("isContaining", "True if the point is contained within the bounds of the panels, false if it is not for each point provided.")]
107+
public static List<bool> IsContaining(this List<Panel> panels, List<Point> points, bool acceptOnEdges = false, double tolerance = BH.oM.Geometry.Tolerance.Distance)
108+
{
109+
if (panels == null)
98110
{
99-
BH.Engine.Base.Compute.RecordError("Cannot query is a collection of panels contains a point if the point is null.");
100-
return false;
111+
BH.Engine.Base.Compute.RecordError("Cannot query if a collection of panels contains a point if the panels are null.");
112+
return new List<bool>() { false };
101113
}
102114

103115
List<Plane> planes = new List<Plane>();
@@ -107,6 +119,62 @@ public static bool IsContaining(this List<Panel> panels, Point point, bool accep
107119
List<Point> ctrPoints = panels.SelectMany(x => x.Polyline().IControlPoints()).ToList();
108120
BoundingBox boundingBox = BH.Engine.Geometry.Query.Bounds(ctrPoints);
109121

122+
return points.Select(point => IsContaining(panels, planes, boundingBox, point, acceptOnEdges)).ToList();
123+
}
124+
125+
[Description("Defines whether an Environment Space contains each of a provided list of points.")]
126+
[Input("space", "An Environment Space object defining a perimeter to build a 3D volume from and check if the volume contains the provided point.")]
127+
[Input("spaceHeight", "The height of the space.", typeof(BH.oM.Quantities.Attributes.Length))]
128+
[Input("points", "The points being checked to see if it is contained within the bounds of the 3D volume.")]
129+
[Input("acceptOnEdges", "Decide whether to allow the point to sit on the edge of the space, default false.")]
130+
[Output("isContaining", "True if the point is contained within the space, false if it is not.")]
131+
public static List<bool> IsContaining(this Space space, double spaceHeight, List<Point> points, bool acceptOnEdges = false)
132+
{
133+
List<Panel> panelsFromSpace = space.ExtrudeToVolume(spaceHeight);
134+
return panelsFromSpace.IsContaining(points, acceptOnEdges);
135+
}
136+
137+
[Description("Defines whether an Environment Space contains a provided Element.")]
138+
[Input("space", "An Environment Space object defining a perimeter to build a 3D volume from and check if the volume contains the provided element.")]
139+
[Input("spaceHeight", "The height of the space.", typeof(BH.oM.Quantities.Attributes.Length))]
140+
[Input("elements", "The elements being checked to see if they are contained within the bounds of the 3D volume.")]
141+
[Input("acceptOnEdges", "Decide whether to allow the element's point to sit on the edge of the space, default false.")]
142+
[Output("isContaining", "True if the point is contained within the space, false if it is not.")]
143+
public static List<bool> IsContaining(this Space space, double spaceHeight, List<IElement> elements, bool acceptOnEdges = false, bool acceptPartialContainment = false)
144+
{
145+
List<Panel> panelsFromSpace = space.ExtrudeToVolume(spaceHeight);
146+
List<List<Point>> pointLists = new List<List<Point>>();
147+
148+
foreach (IElement elem in elements)
149+
{
150+
List<Point> points = elem.IControlPoints();
151+
pointLists.Add(points);
152+
}
153+
return panelsFromSpace.IsContaining(pointLists, acceptOnEdges, acceptPartialContainment);
154+
}
155+
156+
157+
/***************************************************/
158+
/**** Private Methods ****/
159+
/***************************************************/
160+
161+
[Description("Defines whether a point lies within a collection of panels using their primitive planes and bounds.")]
162+
[Input("panels", "A collection of Environment Panels to check with.")]
163+
[Input("planes", "Planes corresponding to each panel for intersection calculations.")]
164+
[Input("boundingBox", "The bounding box of the collection of panels.")]
165+
[Input("point", "The point to check to see if it is contained within the bounds of the panels.")]
166+
[Input("acceptOnEdges", "Decide whether to allow the point to sit on the edge of the panel, default false.")]
167+
[Input("tolerance", "Distance tolerance to use to determine intersections.")]
168+
[Output("isContaining", "True if the point is contained within the bounds of the panels, false if it is not for each point provided.")]
169+
private static bool IsContaining(this List<Panel> panels, List<Plane> planes, BoundingBox boundingBox, Point point, bool acceptOnEdges = false, double tolerance = BH.oM.Geometry.Tolerance.Distance)
170+
{
171+
//Return if point is null even without checking boundingBox.IsContaining(point)
172+
if (point == null)
173+
{
174+
BH.Engine.Base.Compute.RecordError("Cannot query if a collection of panels contains a point if the point is null.");
175+
return false;
176+
}
177+
110178
if (!BH.Engine.Geometry.Query.IsContaining(boundingBox, point, true, tolerance))
111179
return false;
112180

@@ -168,20 +236,40 @@ public static bool IsContaining(this List<Panel> panels, Point point, bool accep
168236
return isContained; //If the number of intersections is odd the point is outsde the space
169237
}
170238

171-
[Description("Defines whether an Environment Space contains a provided point.")]
172-
[Input("space", "An Environment Space object defining a perimeter to build a 3D volume from and check if the volume contains the provided point.")]
173-
[Input("spaceHeight", "The height of the space.", typeof(BH.oM.Quantities.Attributes.Length))]
174-
[Input("points", "The points being checked to see if it is contained within the bounds of the 3D volume.")]
175-
[Input("acceptOnEdges", "Decide whether to allow the point to sit on the edge of the space, default false.")]
176-
[Output("isContaining", "True if the point is contained within the space, false if it is not.")]
177-
public static List<bool> IsContaining(this Space space, double spaceHeight, List<Point> points, bool acceptOnEdges = false)
239+
[Description("Defines whether a collection of Environment Panels contains each of a provided list of list of points.")]
240+
[Input("panels", "A collection of Environment Panels to check with.")]
241+
[Input("pointLists", "The List of Lists of points to check to see if each List of points are contained within the bounds of the panels.")]
242+
[Input("acceptOnEdges", "Decide whether to allow the points to sit on the edge of the panel, default false.")]
243+
[Input("acceptPartialContainment", "Decide whether to allow some of the points to sit outside the panels as long as at least one is within them.")]
244+
[Output("isContaining", "True if the points of each sublist are contained within the bounds of the panels, false if it is not for each sublist of points provided.")]
245+
private static List<bool> IsContaining(this List<Panel> panels, List<List<Point>> pointLists, bool acceptOnEdges = false, bool acceptPartialContainment = false, double tolerance = BH.oM.Geometry.Tolerance.Distance)
178246
{
179-
List<Panel> panelsFromSpace = space.ExtrudeToVolume(spaceHeight);
180-
return points.Select(x => panelsFromSpace.IsContaining(x, acceptOnEdges)).ToList();
181-
}
182-
}
183-
}
247+
if (panels == null)
248+
{
249+
BH.Engine.Base.Compute.RecordError("Cannot query if a collection of panels contains a point if the panels are null.");
250+
return new List<bool>() { false };
251+
}
184252

253+
List<Plane> planes = new List<Plane>();
254+
foreach (Panel be in panels)
255+
planes.Add(be.Polyline().IControlPoints().FitPlane(tolerance));
185256

257+
List<Point> ctrPoints = panels.SelectMany(x => x.Polyline().IControlPoints()).ToList();
258+
BoundingBox boundingBox = BH.Engine.Geometry.Query.Bounds(ctrPoints);
186259

260+
List<bool> areContained = new List<bool>();
187261

262+
foreach (List<Point> pts in pointLists)
263+
{
264+
bool isContained = false;
265+
if (acceptPartialContainment)
266+
isContained = pts.Any(point => IsContaining(panels, planes, boundingBox, point, acceptOnEdges));
267+
else
268+
isContained = pts.All(point => IsContaining(panels, planes, boundingBox, point, acceptOnEdges));
269+
areContained.Add(isContained);
270+
}
271+
272+
return areContained;
273+
}
274+
}
275+
}

Lighting_Engine/Query/Geometry.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* This file is part of the Buildings and Habitats object Model (BHoM)
3+
* Copyright (c) 2015 - 2023, the respective contributors. All rights reserved.
4+
*
5+
* Each contributor holds copyright over their respective contributions.
6+
* The project versioning (Git) records all such contribution source information.
7+
*
8+
*
9+
* The BHoM is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License as published by
11+
* the Free Software Foundation, either version 3.0 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* The BHoM is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU Lesser General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public License
20+
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
21+
*/
22+
23+
using System;
24+
using System.Collections.Generic;
25+
using System.Linq;
26+
using System.Text;
27+
using System.Threading.Tasks;
28+
29+
using BH.oM.Lighting;
30+
using BH.oM.Base.Attributes;
31+
using System.ComponentModel;
32+
using BH.oM.Geometry;
33+
using BH.oM.Lighting.Elements;
34+
35+
namespace BH.Engine.Lighting
36+
{
37+
public static partial class Query
38+
{
39+
[Description("Gets the geometry of a Luminaire as a Point.")]
40+
[Input("luminaire", "Element to get the Point from.")]
41+
[Output("point", "The geometry of the Element.")]
42+
public static Point Geometry(this Luminaire luminaire)
43+
{
44+
if(luminaire == null)
45+
{
46+
BH.Engine.Base.Compute.RecordError("Cannot query the geometry of a null luminaire.");
47+
return null;
48+
}
49+
50+
return luminaire.Position;
51+
}
52+
}
53+
}

0 commit comments

Comments
 (0)