Hi everyone
I’m learning how to find elements by using the ray tracing method.
I just learned how to find the distance to the selected element from a specified point by using the ReferenceWithContext method.
but got lost when I’m trying to figure it out how to find if there any model lines intersected with the selected element.
Anyone can give me some tips?
BTW Is it possible to find the intersected line from the linked DWG?
Thanks
Dear Sarkate,
Here are some answers from a recent similar discussion:
Best regards,
Jeremy
Hi Jeremy
Thanks for your info
I project a ray from the center point of a beam to the end point. but I'm only able to find structural columns by using the ReferenceIntersector
It only returns the select element when i'm using the BuiltInCategory.OST_StructuralFraming filter.
and nothing happen while using BuiltInCategory.OST_Lines filter to find the intersected lines.
any sugestions?
ElementCategoryFilter filter = new ElementCategoryFilter(BuiltInCategory.OST_StructuralFraming); ReferenceIntersector refIntersector = new ReferenceIntersector(filter,FindReferenceTarget.Element, (View3D)doc.ActiveView); ReferenceWithContext refWithContext = refIntersector.FindNearest(Center,end0); double proximity = refWithContext.Proximity; FamilyInstance fi = doc.GetElement(refWithContext.GetReference()) as FamilyInstance;
Dear Sarkate,
If you say you are trying to shoot a ray to intersect a line, I would suggest you don't.
Due to mathematical imprecision, I would expect this to be a very unreliable undertaking, even if you can get it to work occasionally (or ever).
Cheers,
Jeremy
Depending on wether or not precision is an issue, you could try finding element intersecting the boundingbox of your element. I use this method to find collisions with an element. The only problem is, due to the fact that the BoundingBox is a rectangular box containing your element, it is bigger than the actual element. So you might think there's an intersection when there's not.
UIApplication uiApp2 = commandData.Application;
UIDocument uiDoc2 = uiApp2.ActiveUIDocument;
// Select something to use as base bounding box.
Reference r_2 = uiDoc2.Selection.PickObject(
ObjectType.Element, "Chose the element to check for collisions");
// Find the bounding box from the selected
// object and convert to outline.
Element f2 = doc.GetElement(r_2.ElementId);
BoundingBoxXYZ bb2 = f2.get_BoundingBox(
doc.ActiveView);
Outline outline2 = new Outline(bb2.Min, bb2.Max);
// Create a BoundingBoxIntersectsFilter to
// find everything intersecting the bounding
// box of the selected element.
BoundingBoxIntersectsFilter bbfilter2
= new BoundingBoxIntersectsFilter(outline2);
// Use a view to construct the filter so we
// get only visible elements. For example,
// the analytical model will be found otherwise.
FilteredElementCollector collector2
= new FilteredElementCollector(
doc, doc.ActiveView.Id);
// Lets also exclude the element selected.
ICollection<ElementId> idsExclude2
= new List<ElementId>();
idsExclude2.Add(f2.Id);
// Get the set of elements that pass the
// criteria. Note both filters are quick,
// so order is not so important.
collector2.Excluding(idsExclude2)
.WherePasses(bbfilter2);
// Generate a report to display in the dialog.
int nCount2 = 0;
string report2 = string.Empty;
foreach (Element e in collector2)
{
string name = e.Name;
report2 += "\nName= " + name
+ " Element Id: " + e.Id.ToString();
nCount2++;
}
string aux2 = "There are " + nCount2.ToString()
+ " elements with possible collisions" +
report2;
TaskDialog.Show("Rapport", aux2);
Depending on the element you want to find intersection with (maybe only model lines in your case) you might want to add a filter to only keep model lines.
If I remember correctly, my code is actually from Jeremy who just answered to you. If you haven't checked out his blog yet you should, it's full of useful informations.
Hope this helps.
Jordi
Hi JoAtt
Thanks for your reply
I've been playing with the Bounding Box Method. I got the similar code from the Jeremy's Building Coder Blog.
I was pretty happy at the beginning because I'm able to grab the model line but got stucked while I'm trying to control the direction and the size the bounding box. Because I need to determine on witch end of a beam that a line is closer to. I was trying to obtain the bounding box outline from the center of the bounding box:
BoundingBoxXYZ bb = r.get_BoundingBox(doc.ActiveView);
XYZ BCenter = (bb.Min + bb.Max)/2.0;
Outline outline = new Outline(BCenter,bb.Max));
but this only able draw a outline from Left to Right so I'm only can get the intersection on one end.
and there is another problem when the beam is on an angle, the bounding box size will be incrested, and grab other lines whitch are not intersected to the selected beam.
Still keep thinking
I never created a BoundingBox with my own measurement, only from an element, so I don't really know. The only similar thing I can think of is when I created my family with a safety zone :
Say my family is a cube, plain and simple. Around this cube I create another bigger cube and i set the material to the bigger cube to something transparent, say glass. That way I could detect if another object was too close to the small cube i.e. intersecting the glass cube.
Not sure if it can be applied to your problem but I haven't any other ideas for now.
Jordi
Did it work ?
I'm quite curious myself since I wasn't aware that I could use ElementIntersectsSolidFilter for my own purpose. I tried using it but it finds intersections that doesnt exist. I must use it wrong.
If you manage to make it work, please let me know.
Jordi
Hi, Jordi
No,I still can't make it work
I have a working find column with solid sphere code and I modified the IEnumerable collector and filter as follow, but not line is being found.
not sure if I did worng on the filter?
IEnumerable<Element> Mline = new FilteredElementCollector(doc)
.OfClass(typeof(CurveElement))
.WherePasses(new ElementIntersectsSolidFilter(solid));
SelElementSet selSet = SelElementSet.Create();
foreach (Element e in Mline)
{
ModelLine ml = e as ModelLine;
if (ml == null) continue;
selSet.Add(e);
uidoc.Selection.Elements = selSet;
uidoc.RefreshActiveView();
foundLine = true;
break;
}
I personnaly tried out this :
// Find intersections between family instances and a selected element Reference reference = uidoc.Selection.PickObject(ObjectType.Element, "Select element that will be checked for intersection with all family instances"); Element element = doc.GetElement(reference.ElementId); GeometryElement geomElement = element.get_Geometry(new Options()); Solid solid = null; foreach (GeometryObject geomObj in geomElement) { solid = geomObj as Solid; if (solid != null) break; } FilteredElementCollector collector = new FilteredElementCollector(doc); collector.OfClass(typeof(FamilyInstance)); collector.WherePasses(new ElementIntersectsSolidFilter(solid)); // Apply intersection filter to find matches TaskDialog.Show("Revit", collector.Count() + " family instances intersect with the selected element (" + element.Category.Name + " id:" + element.Id + ")");
It's from the Revit2014API.chm with a few modifications. Taken from the "ElementIntersectsSolidFilter Class" page.
Problem is, solid stays null the whole time so the ElementIntersectsSolidFilter(solid) can't work and cause an error. As soon as I can find the time, I'll try something that looks like you did and post results.
Thanks for the help !
Jordi
I just managed to make it work for me. Note that I only look for families so that may not apply directly to your problem.
UIApplication uiApp = commandData.Application;
UIDocument uiDoc = uiApp.ActiveUIDocument;
Reference reference = uiDoc.Selection.PickObject(ObjectType.Element, "Chose an element to check for collisions");
Element element = doc.GetElement(reference.ElementId);
FilteredElementCollector collector = new FilteredElementCollector(doc);
collector.OfClass(typeof(FamilyInstance));
collector.WherePasses(new ElementIntersectsElementFilter(element));
TaskDialog.Show("Rapport", collector.Count() + " objects having collisions with the selected element : (" + element.Category.Name + " id:" + element.Id + ")");
int nCount = 0;
string report = string.Empty;
foreach (Element e in collector)
{
string name = e.Name;
report += "\nName = " + name
+ " Element Id: " + e.Id.ToString();
nCount++;
}
string aux = "There is " + nCount.ToString()
+ " element(s) colliding with the placed element" +
report;
TaskDialog.Show("Rapport", aux);
Can't find what you're looking for? Ask the community or share your knowledge.