To find elements that are intersecting a geometry I am using the example post by Jeremy in his blog http://thebuildingcoder.typepad.com/blog/2010/12/find-intersecting-elements.html. But the bounding box is always paralell to the axis X, Y and Z and this may cause a problem, like return elements that are not really clashing, because sometimes the bounding box it's not always coincident with the geometry because the family instance is rotated. Besides that, there is the problem that the bounding box will consider the geometry of the symbol and not the instance, and will consider the flipped geometry too, it means that the bounding box is bigger than I am looking for. Is there a way to get the real geometry that are in the currently view ? How can I solve this problem ?
There are many way to address this. Generally, when performing clash detection, you will always run a super fast pre-processing step first to determine candidate elements, and then narrow down the search step by step more precisely in following steps. In this case, you can consider the bounding box intersection the first step, and then perform post-processing afterwards to narrow down the result to your exact goal.
One important question is: does the bounding box really give you all the elements you need, plus more? Are you sure there are none missing?
Once that is settled, all you need to do is add post-processing steps applying the detailed considerations that you care about.
A simple one might be: are all the target element geometry vertices contained in the target volume?
A more complex one might involve retrieving the full solid of the target element and the target volume and performing a Boolean intersection between them to determine completely and exactly whether they intersect, are disjunct, or contained in each other.
Many others are conceivable.
I am using another strategy that is acess the geometry of the instance to verify if the face of the family instace are clashing with a closer conduit.
class FindIntersection
{
public Conduit ConduitRun { get; set; }
public FamilyInstance Jbox { get; set; }
public List<Conduit> GetListOfConduits = new List<Conduit>();
public FindIntersection(FamilyInstance jbox, UIDocument uiDoc)
{
XYZ jboxPoint = (jbox.Location as LocationPoint).Point;
FilteredElementCollector filteredCloserConduits = new FilteredElementCollector(uiDoc.Document);
List<Element> listOfCloserConduit = filteredCloserConduits.OfClass(typeof(Conduit)).ToList().Where(x =>
((x as Conduit).Location as LocationCurve).Curve.GetEndPoint(0).DistanceTo(jboxPoint) < 30 ||
((x as Conduit).Location as LocationCurve).Curve.GetEndPoint(1).DistanceTo(jboxPoint) < 30).ToList();
//getting the location of the box and all conduit around.
Options opt = new Options();
opt.View = uiDoc.ActiveView;
GeometryElement geoEle = jbox.get_Geometry(opt);
//getting the geometry of the element to acess the geometry of the instance.
foreach (GeometryObject geomObje1 in geoEle)
{
GeometryElement geoInstance = (geomObje1 as GeometryInstance).GetInstanceGeometry();
//the geometry of the family instance can be acess by this method that returns a GeometryElement type.
//so we must get the GeometryObject again to acess the Face of the family instance.
if (geoInstance != null)
{
foreach (GeometryObject geomObje2 in geoInstance)
{
Solid geoSolid = geomObje2 as Solid;
if (geoSolid != null)
{
foreach (Face face in geoSolid.Faces)
{
foreach (Element cond in listOfCloserConduit)
{
Conduit con = cond as Conduit;
Curve conCurve = (con.Location as LocationCurve).Curve;
SetComparisonResult set = face.Intersect(conCurve);
if (set.ToString() == "Overlap")
{
//getting the conduit the intersect the box.
GetListOfConduits.Add(con);
}
}
}
}
}
}
}
}
}
Can you please provide a complete minimal reproducible case so we can understand the exact context and analyse what can be done? Maybe you could include one axis-aligned junction box and one that is not, so we can see how ell versus how badly your existing algorithm performs. Thank you!
I summarised this discussion and the results to date in a blog post on filtering for intersecting elements and conduits intersecting a junction box.
Related
class CheckBFS {
public static String bfs(Graph g){
String result = "";
//Checking if the graph has no vertices
if (g.vertices < 1){
return result;
}
//Boolean Array to hold the history of visited nodes (by default-false)
boolean[] visited = new boolean[g.vertices];
for(int i=0;i<g.vertices;i++)
{
//Checking whether the node is visited or not
if(!visited[i])
{
result = result + bfsVisit(g, i, visited);
}
}
return result;
}
public static String bfsVisit(Graph g, int source, boolean[] visited) {
String result = "";
//Create Queue for Breadth First Traversal and enqueue source in it
Queue<Integer> queue = new Queue<>(g.vertices);
queue.enqueue(source);
visited[source] = true;
//Traverse while queue is not empty
while (!queue.isEmpty()) {
//Dequeue a vertex/node from queue and add it to result
int current_node = queue.dequeue();
result += String.valueOf(current_node);
//Get adjacent vertices to the current_node from the array,
//and if they are not already visited then enqueue them in the Queue
DoublyLinkedList<Integer>.Node temp = null;
if(g.adjacencyList[current_node] != null)
temp = g.adjacencyList[current_node].headNode;
while (temp != null) {
if (!visited[temp.data]) {
queue.enqueue(temp.data);
visited[temp.data] = true; //Visit the current Node
}
temp = temp.nextNode;
}
}//end of while
return result;
}
public static void main(String args[]) {
Graph g = new Graph(5);
g.addEdge(0,1);
g.addEdge(0,2);
g.addEdge(1,3);
g.addEdge(1,4);
System.out.println("Graph1:");
g.printGraph();
System.out.println("BFS traversal of Graph1 : " + bfs(g));
System.out.println();
Graph g2 = new Graph(5);
g2.addEdge(0,1);
g2.addEdge(0,4);
g2.addEdge(1,2);
g2.addEdge(3,4);
System.out.println("Graph2:");
g2.printGraph();
System.out.println("BFS traversal of Graph2 : " + bfs(g2));
}
}
hello,guys! I know this may sound stupid but I am very new to coding and I have no one in real life to seek help for.
My question is: could anybody explain bfsVisit method to me?
especially the code below, so we created a queue to store all the nodes/vertices that we have visited and the part below is how we "extract" nodes/ vertices from the doublyLinkedList one by one and put them into the queue?
DoublyLinkedList.Node temp = null;
if(g.adjacencyList[current_node] != null)
temp = g.adjacencyList[current_node].headNode;
while (temp != null) {
if (!visited[temp.data]) {
queue.enqueue(temp.data);
visited[temp.data] = true; //Visit the current Node
}
temp = temp.nextNode;
}
I am not sure if I get the logic of all the two methods in class CheckBFS
why should we separate the methods into bfs and bfsVisit?
So bfs is the primary method that count/store/record the nodes we visited and bfsVisit is actually the method that help us traverse the array of linkedlist?
Thanks very much!!!!
could anybody explain bfsVisit method to me?
bfsVisit intends to visit all nodes that can be reached from the given source node. Here are some aspects of that part of the algorithm:
visited is important, as it makes sure that the algorithm will not fall into an infinite loop when it encounters a cycle in the graph. Imagine for instance three nodes A, B, and C, where A connects to B, and B connects to C, and C connects to A. We don't want the algorithm to just keep running in circles, revisiting the same nodes over and over again. And so when A is visited the first time, it is marked as visited in the visited boolean array. When the algorithm would meet A again, it would skip it.
queue is something that is typical for breadth-first traversals: it ensures that the nodes that are closest (in terms of edges) to the source node are visited first. So first the nodes that are only one edge apart from the source node are visited, then those that are two edges apart, ...etc. To achieve this order we need a first-in-first-out data structure, which is what queue is.
especially the code below, so we created a queue to store all the nodes/vertices that we have visited and the part below is how we "extract" nodes/ vertices from the doublyLinkedList one by one and put them into the queue?
Yes. The aspect of the doubly linked list is not that important: it happens to be the data structure that the Graph class uses to give access to a node's neighboring nodes. But that is an implementation detail of Graph and is not essential for the breadth-first algorithm. What matters is that somehow you can get hold of the neighboring nodes. This could have been a vector or an array, or any collection data type that could provide you with the neighbors. It is determined by the Graph class.
temp represents that list of neighbors. I find the name of that variable not helpful. Its name could have been more descriptive, like neighbor.
That inner loop intends to loop over all direct neighbors of a given node current_node. For each of the neighbors it is first assured that it was not visited before. In that case it is marked as visited and put at the end of the queue. The queue will hold it until it becomes the first in the queue, and then it will play the role of current_node so that it expends to its own neighbors, ...etc.
temp = temp->nextNode just picks the next neighbor from the list of neighbors. As I stated before, this is an implementation detail and would have looked different if the collection of neighbors would have been provided in a different data structure. What matters is that this loop goes through the list of neighbors and deals with those that were not visited before.
why should we separate the methods into bfs and bfsVisit?
Some of the reasons:
bfsVisit can only visit nodes that are connected to the source node. If the graph happens to be a graph with disconnected components. In that case it is impossible for bfsVisit to find all nodes of the graph. That's why we have the loop in bfs: it makes sure to run bfsVisit on each component of the graph, as otherwise we would only have visited one component.
bfs actually does not perform a BFS traversal itself. I should stress here that the name bfs for the main function is thus a bit misleading: BFS is a term that only makes sense for the collection of nodes in one component. The loop we find in bfs would actually look exactly the same if the purpose was to perform a dfs traversal! That loop's purpose is only to ensure that all nodes of a graph are visited even when the graph has multiple components. Notice how bfs does not use a queue for its own purposes. It just iterates the nodes in their numerical order without any regard of edges. This is entirely different from bfsVisit which looks for connected nodes, following edges.
bfsVisit is also a kind of helper function: it receives arguments that the main function bfs did not get itself as arguments, but manages itself:
visited is the most important of those. bfs starts out by the assumption that no nodes have been visited at all. bfsVisit however needs to tell bfs which nodes it had visited once it completes.
source is the starting point for bfsVisit: it is always one of the nodes that belong to a graph component that was not visited before. This is different from bst which just chooses itself which nodes to visit without any specific node given by the caller.
I hope this clarifies it.
I have a 2D matrix with 0s and 1s - respectively representing Water and Land. It is used to generate an animated gif with Perlin noise (moving water and waves clashing on shores...).
However I wish to refactor my code and use polymorphism in the following manner:
For each element in my matrix, based on the value, I wish to create a new WaterTile or LandTile (which will represent a 30x30 set of pixels that are either a mixture of blue for water, and some combinations of green/yellow/blue for land).
WaterTile and LandTile will be inherited from BaseTile (this is an abstract class), having just 2 vars (x, y for coordinates) and a draw() method (this method for the BaseTile class does nothing, its just there if it has to be defined).
Child classes will be overriding the draw() method.
Map will be a 2D array that whose elements will be WaterTiles and LandTiles.
After that, in my main method, I will have this (pseudocode for simplicity, i is index of row, j is index of element in that row):
foreach (row in matrix) {
foreach (element in row) {
if (matrix[i][j] == 0) map[i][j] == new WaterTile();
else map[i][j] == new LandTile();
}
}
After this I will need to invoke more methods for the LandTiles, and then have a new foreach loop, simply having
map[i][j].draw();//invoking draw method based on type
I know this can be done in other ways, but i wish to avoid having if statements that check for the type and call the draw method based on the type, and also practice clean code and learn something new.
If someone can provide me a simple example, ive looked at some already but havent found what I want.
Put the different actions inside the if statement you already have.
Or, just call the draw method, and let each instance do what it is does with draw.
Or encapsulate the if inside a function and use that.
I need to find out the number of Reference planes and their names which are passing through a selected wall. I can get all the reference planes for a particular document but how shall I do this for a particular wall.
You help would be appreciated!
Thanks.
If the ElementIntersectFilter doesn't work for your needs, you'll have to extract the geometry of the wall and reference plane and work with those directly.
Intersecting the reference planes with the wall solids can work, but there's a simpler answer that will work, if I understand your question correctly. I'm assuming you only want the walls where the green line of the ref plane intersects, rather than treating the reference plane object as an infinite geometric plane. In the screenshot below, I assume you want to find the checkmarks, but not the red X's. I'm also assuming you're looking at this as a plan exercise, and not specifically setting the vertical extents of the reference plane (this is just based on how I've seen most people use Revit). The following function takes as inputs a single wall and a list of ref planes (you mentioned you already have the collection of all ref planes) and will return a list of ref planes which intersect the wall.
public static List<ReferencePlane> getRefPlanesIntersectingWall( Wall wal, List<ReferencePlane> refPlanesIn)
{
//simplify this to a 2D problem, using the location curve of the wall
List<ReferencePlane> refPlanesOut = new List<ReferencePlane>();
LocationCurve wallLocation = wal.Location as LocationCurve;
Curve wallCurve = wallLocation.Curve;
Double wallZ = wallLocation.Curve.GetEndPoint(0).Z;
foreach (ReferencePlane rp in refPlanesIn)
{
XYZ startPt = new XYZ(rp.BubbleEnd.X, rp.BubbleEnd.Y, wallZ);
XYZ endPt = new XYZ(rp.FreeEnd.X, rp.FreeEnd.Y, wallZ);
Line rpLine = Line.CreateBound(startPt, endPt);
SetComparisonResult test = wallCurve.Intersect(rpLine);
if (test == SetComparisonResult.Overlap ||
test == SetComparisonResult.Subset ||
test == SetComparisonResult.Superset ||
test == SetComparisonResult.Equal )
{
refPlanesOut.Add(rp);
}
}
return refPlanesOut;
}
I would start by trying the built-in ElementIntersectFilter. The documentation has a nice example, replace "FamilyInstance" with "referencePlane" and that may do it.
http://www.revitapidocs.com/2017/19276b94-fa39-64bb-bfb8-c16967c83485.htm
If that doesn't work, you'll need to extract the solid of the wall and intersect with the reference plane.
Let's say that I want to calculate the distance between two geometries with JTS, but there is another one in the middle that I can't go across (as if it was a wall). It could look like this :
I wonder how I could calculate that.
In this case, these shapes geom1 and geom2 are 38.45 meters away, as I calculate it straight away. But if I don't want go across that line, I should surround it by the Northern sides, and distance would probably be more than 70 meters away.
We can think that we could have a line a polygon or whatever in the middle.
I wonder if there is any built in function in JTS, or some other thing I could you. I guess if there is anything out there, I should check for some other workaround, as trying to solve complex routing problems is beyond my knowledge.
This is the straight away piece of code using JTS for the distance, which would not still take into account the Geometry in the middle.
import org.apache.log4j.Logger;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
public class distanceTest {
private final static Logger logger = Logger.getLogger("distanceTest");
public static void main(String [] args) {
//Projection : EPSG:32631
// We build one of the geometries on one side
String sGeom1="POLYGON ((299621.3240601513 5721036.003245114, 299600.94820609683 5721085.042327096, 299587.7719688322 5721052.9152064435, 299621.3240601513 5721036.003245114))";
Geometry geom1=distanceTest.buildGeometry(sGeom1);
// We build the geometry on the other side
String sGeom2=
"POLYGON ((299668.20990794065 5721092.766132105, 299647.3623194871 5721073.557249224, 299682.8494029705 5721049.148841454, 299668.20990794065 5721092.766132105))";
Geometry geom2=distanceTest.buildGeometry(sGeom2);
// There is a geometry in the middle, as if it was a wall
String split=
"LINESTRING (299633.6804935104 5721103.780167559, 299668.99872434285 5720999.981241705, 299608.8457218057 5721096.601805294)";
Geometry splitGeom=distanceTest.buildGeometry(split);
// We calculate the distance not taking care of the wall in the middle
double distance = geom1.distance(geom2);
logger.error("Distance : " + distance);
}
public static Geometry buildGeometry(final String areaWKT) {
final WKTReader fromText = new WKTReader();
Geometry area;
try {
area = fromText.read(areaWKT);
}
catch (final ParseException e) {
area = null;
}
return area;
}
}
This works for SQL, I hope you have the same or similar methods at your disposal.
In theory, in this instance you could create a ConvexHull containing the two geometries AND your "unpassable" geometry.
Geometry convexHull = sGeom1.STUnion(sGeom2).STUnion(split).STConvexHull();
Next, extract the border of the ConvexHull to a linestring (use STGeometry(1) - I think).
Geometry convexHullBorder = convexHull.STGeometry(1);
EDIT: Actually, with Geometry you can use STExteriorRing().
Geometry convexHullBorder = convexHull.STExteriorRing();
Lastly, pick one of your geometries, and for each shared point with the border of the ConvexHull, walk the border from that point until you reach the first point that is shared with the other geometry, adding the distance between the current and previous point at each point reached. If the second point you hit belongs to the same geometry as you are walking from, exit the loop and move on to the next to reduce time. Repeat for the second geometry.
When you've done this for all possibilities, you can simply take the minimum value (there will be only two - Geom1 to Geom2 and Geom2 to Geom1) and there is your answer.
Of course, there are plenty of scenarios in which this is too simple, but if all scenarios simply have one "wall" in them, it will work.
Some ideas of where it will not work:
The "wall" is a polygon, fully enveloping both geometries - but then how would you ever get there anyway?
There are multiple "walls" which do not intersect each other (gaps between them) - this method will ignore those passes in between "walls". If however multiple "walls" intersect, creating essentially one larger "wall" the theory will still work.
Hope that makes sense?
EDIT: Actually, upon further reflection there are other scenarios where the ConvexHull approach will not work, for instance the shape of your polygon could cause the ConvexHull to not produce the shortest path between geometries and your "walls". This will not get you 100% accuracy.
I have the following class:
public class Vertex() {
private double xCoord;
private double yCoord;
private ArrayList<Vertex> neighborList();
}
And I want to support adding/removing vertices to the neighborList such that the points are listed in CCW order around this vertex (which point is first in the list doesn't matter). If points are collinear, nearer points to this should be first. I've tried several methods but so far have always been able to find a counter example that doesn't work for the given method.
Does anyone have a good idea of how to do this in a simple and efficient manner?
Express the point coordinates in the polar form
t = atan2(Y-Yo, X-Xo)
r = sqrt((X-Xo)^2 + (Y-Yo)^2)
and use lexicographical ordering on angle then radius.