Skip to content

Environment_Engine: Added ElementsInSpace and dependant IsContaining methods / optimisations #3195

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions Environment_Engine/Compute/ElementsInSpace.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* This file is part of the Buildings and Habitats object Model (BHoM)
* Copyright (c) 2015 - 2023, the respective contributors. All rights reserved.
*
* Each contributor holds copyright over their respective contributions.
* The project versioning (Git) records all such contribution source information.
*
*
* The BHoM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* The BHoM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using BH.oM.Environment.Elements;
using BH.oM.Architecture.Elements;

using BH.Engine.Geometry;
using BH.oM.Geometry;

using BH.oM.Base.Attributes;
using System.ComponentModel;

using BH.oM.Analytical.Elements;
using BH.oM.Dimensional;

namespace BH.Engine.Environment
{
public static partial class Compute
{
[Description("Gets the elements that lie within the provided space.")]
[Input("space", "An Environment Space object defining a perimeter to build a 3D volume from and check if the volume contains the provided point.")]
[Input("spaceHeight", "The height of the space.", typeof(BH.oM.Quantities.Attributes.Length))]
[Input("elements", "The elements being checked to see if they are contained within the bounds of the 3D volume.")]
[Input("acceptOnEdges", "Decide whether to allow elements which sit on the edge of the space, default false.")]
[Input("acceptPartial", "Decide whether to include elements only partially within the space, default false.")]
[Output("elements", "The elements from the provided elements that are within the space.")]
public static List<IElement> ElementsInSpace(this Space space, double spaceHeight, List<IElement> elements, bool acceptOnEdges = false, bool acceptPartial = false)
{
if (space == null)
return new List<IElement>();

List<bool> isContaining = space.IsContaining(spaceHeight, elements, acceptOnEdges, acceptPartial);

return elements
.Zip(isContaining, (elem, inSpace) => new {
elem,
inSpace,
})
.Where(item => item.inSpace)
.Select(item => item.elem)
.ToList();
}
}
}
144 changes: 116 additions & 28 deletions Environment_Engine/Query/IsContaining.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,16 @@
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using BH.oM.Environment;
using BH.oM.Environment.Elements;
using BH.oM.Base;

using BH.oM.Geometry;
using BH.Engine.Geometry;

using BH.Engine.Spatial;
using BH.oM.Base.Attributes;
using BH.oM.Dimensional;
using BH.oM.Environment.Elements;
using BH.oM.Geometry;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

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

if(point == null)
List<Plane> planes = new List<Plane>();
foreach (Panel be in panels)
planes.Add(be.Polyline().IControlPoints().FitPlane(tolerance));

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

return IsContaining(panels, planes, boundingBox, point, acceptOnEdges);
}

[Description("Defines whether a collection of Environment Panels contains each of a provided list of points.")]
[Input("panels", "A collection of Environment Panels to check with.")]
[Input("points", "The points to check to see if each point is contained within the bounds of the panels.")]
[Input("acceptOnEdges", "Decide whether to allow the point to sit on the edge of the panel, default false.")]
[Output("isContaining", "True if the point is contained within the bounds of the panels, false if it is not for each point provided.")]
public static List<bool> IsContaining(this List<Panel> panels, List<Point> points, bool acceptOnEdges = false, double tolerance = BH.oM.Geometry.Tolerance.Distance)
{
if (panels == null)
{
BH.Engine.Base.Compute.RecordError("Cannot query is a collection of panels contains a point if the point is null.");
return false;
BH.Engine.Base.Compute.RecordError("Cannot query if a collection of panels contains a point if the panels are null.");
return new List<bool>() { false };
}

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

return points.Select(point => IsContaining(panels, planes, boundingBox, point, acceptOnEdges)).ToList();
}

[Description("Defines whether an Environment Space contains each of a provided list of points.")]
[Input("space", "An Environment Space object defining a perimeter to build a 3D volume from and check if the volume contains the provided point.")]
[Input("spaceHeight", "The height of the space.", typeof(BH.oM.Quantities.Attributes.Length))]
[Input("points", "The points being checked to see if it is contained within the bounds of the 3D volume.")]
[Input("acceptOnEdges", "Decide whether to allow the point to sit on the edge of the space, default false.")]
[Output("isContaining", "True if the point is contained within the space, false if it is not.")]
public static List<bool> IsContaining(this Space space, double spaceHeight, List<Point> points, bool acceptOnEdges = false)
{
List<Panel> panelsFromSpace = space.ExtrudeToVolume(spaceHeight);
return panelsFromSpace.IsContaining(points, acceptOnEdges);
}

[Description("Defines whether an Environment Space contains a provided Element.")]
[Input("space", "An Environment Space object defining a perimeter to build a 3D volume from and check if the volume contains the provided element.")]
[Input("spaceHeight", "The height of the space.", typeof(BH.oM.Quantities.Attributes.Length))]
[Input("elements", "The elements being checked to see if they are contained within the bounds of the 3D volume.")]
[Input("acceptOnEdges", "Decide whether to allow the element's point to sit on the edge of the space, default false.")]
[Output("isContaining", "True if the point is contained within the space, false if it is not.")]
public static List<bool> IsContaining(this Space space, double spaceHeight, List<IElement> elements, bool acceptOnEdges = false, bool acceptPartialContainment = false)
{
List<Panel> panelsFromSpace = space.ExtrudeToVolume(spaceHeight);
List<List<Point>> pointLists = new List<List<Point>>();

foreach (IElement elem in elements)
{
List<Point> points = elem.IControlPoints();
pointLists.Add(points);
}
return panelsFromSpace.IsContaining(pointLists, acceptOnEdges, acceptPartialContainment);
}


/***************************************************/
/**** Private Methods ****/
/***************************************************/

[Description("Defines whether a point lies within a collection of panels using their primitive planes and bounds.")]
[Input("panels", "A collection of Environment Panels to check with.")]
[Input("planes", "Planes corresponding to each panel for intersection calculations.")]
[Input("boundingBox", "The bounding box of the collection of panels.")]
[Input("point", "The point to check to see if it is contained within the bounds of the panels.")]
[Input("acceptOnEdges", "Decide whether to allow the point to sit on the edge of the panel, default false.")]
[Input("tolerance", "Distance tolerance to use to determine intersections.")]
[Output("isContaining", "True if the point is contained within the bounds of the panels, false if it is not for each point provided.")]
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)
{
//Return if point is null even without checking boundingBox.IsContaining(point)
if (point == null)
{
BH.Engine.Base.Compute.RecordError("Cannot query if a collection of panels contains a point if the point is null.");
return false;
}

if (!BH.Engine.Geometry.Query.IsContaining(boundingBox, point, true, tolerance))
return false;

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

[Description("Defines whether an Environment Space contains a provided point.")]
[Input("space", "An Environment Space object defining a perimeter to build a 3D volume from and check if the volume contains the provided point.")]
[Input("spaceHeight", "The height of the space.", typeof(BH.oM.Quantities.Attributes.Length))]
[Input("points", "The points being checked to see if it is contained within the bounds of the 3D volume.")]
[Input("acceptOnEdges", "Decide whether to allow the point to sit on the edge of the space, default false.")]
[Output("isContaining", "True if the point is contained within the space, false if it is not.")]
public static List<bool> IsContaining(this Space space, double spaceHeight, List<Point> points, bool acceptOnEdges = false)
[Description("Defines whether a collection of Environment Panels contains each of a provided list of list of points.")]
[Input("panels", "A collection of Environment Panels to check with.")]
[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.")]
[Input("acceptOnEdges", "Decide whether to allow the points to sit on the edge of the panel, default false.")]
[Input("acceptPartialContainment", "Decide whether to allow some of the points to sit outside the panels as long as at least one is within them.")]
[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.")]
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)
{
List<Panel> panelsFromSpace = space.ExtrudeToVolume(spaceHeight);
return points.Select(x => panelsFromSpace.IsContaining(x, acceptOnEdges)).ToList();
}
}
}
if (panels == null)
{
BH.Engine.Base.Compute.RecordError("Cannot query if a collection of panels contains a point if the panels are null.");
return new List<bool>() { false };
}

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

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

List<bool> areContained = new List<bool>();

foreach (List<Point> pts in pointLists)
{
bool isContained = false;
if (acceptPartialContainment)
isContained = pts.Any(point => IsContaining(panels, planes, boundingBox, point, acceptOnEdges));
else
isContained = pts.All(point => IsContaining(panels, planes, boundingBox, point, acceptOnEdges));
areContained.Add(isContained);
}

return areContained;
}
}
}
53 changes: 53 additions & 0 deletions Lighting_Engine/Query/Geometry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* This file is part of the Buildings and Habitats object Model (BHoM)
* Copyright (c) 2015 - 2023, the respective contributors. All rights reserved.
*
* Each contributor holds copyright over their respective contributions.
* The project versioning (Git) records all such contribution source information.
*
*
* The BHoM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* The BHoM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using BH.oM.Lighting;
using BH.oM.Base.Attributes;
using System.ComponentModel;
using BH.oM.Geometry;
using BH.oM.Lighting.Elements;

namespace BH.Engine.Lighting
{
public static partial class Query
{
[Description("Gets the geometry of a Luminaire as a Point.")]
[Input("luminaire", "Element to get the Point from.")]
[Output("point", "The geometry of the Element.")]
public static Point Geometry(this Luminaire luminaire)
{
if(luminaire == null)
{
BH.Engine.Base.Compute.RecordError("Cannot query the geometry of a null luminaire.");
return null;
}

return luminaire.Position;
}
}
}