Why does "ElementId(BuiltInCategory.OST_Walls)" fails within Revit API 2019? - revit-api

I am trying to filter walls. For that I use
categories = List[ElementId]()
myId = ElementId(BuiltInCategory.OST_Walls)
categories.Add(myId)
..but this obviously doesn't return a valid ElementId, as when I print it, it has some negative value (and if I print "doc.GetElement(myId)", I get "None").
Then, indeed when creating the filter...
filter = ParameterFilterElement.Create(doc, "Walls filter", categories)
...I get an ArgumentException.
I'm using Revit 2019 (with pyRevit). As far as I remember, it used to work with Revit 2018, but I don't see any reason it shouldn't anymore. What am I missing?
Thanks a lot!

You can simply use the filtered element collector OfCategory Method.
E.g., check out The Building Coder hints on filtered element collector optimisation.

Apply an ElementCategoryFilter to the collector to get all the walls of the project. By using the following code you can filter any kind of category. I have tried this on Revit 2019.
FilteredElementCollector collector = new FilteredElementCollector(document);
ICollection<Element> walls = collector.OfCategory(BuiltInCategory.OST_Walls).ToElements();

I agree with #Mah Noor answer.
If you need to have a filter with multiple categories, you can use:
ElementCategoryFilter wallFilter = new ElementCategoryFilter(BuiltInCategory.OST_Walls);
ElementCategoryFilter windowFilter = new ElementCategoryFilter(BuiltInCategory.OST_Windows);
LogicalOrFilter wallAndWindowFilter = new LogicalOrFilter(wallFilter, windowFilter);
ICollection<Element> collection = new FilteredElementCollector(doc).WherePasses(wallAndWindowFilter);
Bonus tip, you may want to add .WhereElementIsNotElementType() or .WhereElementIsElementType() to your query.
Best regards
François

Related

How can I set transparent walls in a given view with Revit API?

I try to set transparent walls, using pyRevit. I do the following:
categories = List[ElementId]()
wallCatId = ElementId(BuiltInCategory.OST_Walls)
categories.Add(wallCatId)
ogs = OverrideGraphicSettings()
ogs.SetSurfaceTransparency(70)
t = Transaction(doc, "New parameter filter")
t.Start()
filter = ParameterFilterElement.Create(doc, "Walls filter", categories)
t.Commit()
all_views = FilteredElementCollector(doc).OfClass(View).ToElements()
for i in all_views:
if (i.ViewType == ViewType.ThreeD) or (i.ViewType == ViewType.FloorPlan):
views_to_treat.append(i)
t = Transaction(doc, "New visibility filter")
t.Start()
for i in views_to_treat:
i.AddFilter(filter.Id)
i.SetFilterOverrides(filter.Id, ogs)
t.Commit()
Nothing happens, I don't know why. Is it my "categories" that is wrongly defined (how can I know what kind of ElementId it expects? Is it the Id of the Wall Category? In that case, it should be ok here)? Or is it when applying the filter override to the view?
Any help would be greatly appreciated!
Arnaud.
I can see that you are applying the transparency filter to Walls. I am not 100% sure that this is the most efficient way to achieve this since we can override transparency via Category override. Please keep in mind that Filters are limited as we can apply only a handful of them to the view. There is a max number. I don't remember from top of my head, but there is. Also, order of filters matters, as they can potentially override each other's rules based on order. Either way overriding transparency can be achieved by changing it on a Category like so:
catId = ElementId(BuiltInCategory.OST_Walls)
all_views = FilteredElementCollector(doc).OfClass(View).ToElements()
overrides = OverrideGraphicSettings()
overrides.SetSurfaceTransparency(70)
t = Transaction(doc, "Override Categories")
t.Start()
for i in all_views:
if ((i.ViewType == ViewType.ThreeD) or (i.ViewType == ViewType.FloorPlan)) and (i.IsCategoryOverridable(catId)):
try:
i.SetCategoryOverrides(catId, overrides)
except:
# print out error?
pass
t.Commit()
Also, just a few generic comments. Try to minimize the amount of times you iterate over lists, especially if they are the same items. If you can do what you need to do in the first loop, then that's the best. The above can be simplified even more with list comprehension but I wanted to keep it "obvious" for educational purposes.
I am also checking if Category is overridable before attempting to do so. Why? Because if view category overrides are controlled by a view template, it will not allow us to set the overrides. Also some categories don't have a surface transparency override ex. lines if I remember correctly.
Finally I like to put it all in a try/except statement so that i can catch any issues in my loop and still continue with other items. if I don't do that, and one view fails, we would have failed the whole operation.
This is what the result should be:

Create Dimensions from edge of wall, to sides of openings, to other edge of wall

I've been struggling with this issue off and on for the better part of a year.
As the title says, i wish to dimension from one side of a wall, to both sides of openings (door openings), then terminate at the other end of the wall (vertically and horizontally). I also wish to dimension to all families hosted in the wall, but i have been able to accomplish this using ScottWilson's voodo magic helper class. Found Here: http://thebuildingcoder.typepad.com/blog/2016/04/stable-reference-string-magic-voodoo.html
foreach (ElementId ele in selSet) {
FamilyInstance fi = doc.GetElement(ele) as FamilyInstance;
Reference reference = ScottWilsonVoodooMagic.GetSpecialFamilyReference(fi,ScottWilsonVoodooMagic.SpecialReferenceType.CenterLR,doc);
refs.Append(reference);
pts[i] = ( fi.Location as LocationPoint ).Point;
i++;
}
XYZ offset = new XYZ(0,0,4);
Line line = Line.CreateBound( pts[0]+offset, pts[selSet.Count - 1]+offset );
using( Transaction t = new Transaction( doc ) )
{
t.Start( "dimension embeds" );
Dimension dim = doc.Create.NewDimension(doc.ActiveView, line, refs );
t.Commit();
}
The problem lies in determining the appropriate stable references to the wall faces. I am able to find all faces on a wall, but this gives me 100+ faces to sort through.
If anyone can help me it would be greatly appreciated!
Side note: The closest of gotten is using a casting a ray trace through my panel, then using a reference intersector method to determine references. But i'm really struggling with implementation: http://thebuildingcoder.typepad.com/blog/2015/12/retrieving-wall-openings-and-sorting-points.html
These two posts should provide more than enough to solve all your issues:
Dimension walls by iterating their faces
Dimension walls by shooting a ray
Basically, you need to obtain references to the faces or edges that you wish to attach the dimensioning to. These references can be obtained in several ways. Two common and easy approaches are:
Retrieve the element geometry using the option ComputeReferences set to true and extract the specific face required.
Shoot a ray through the model to determine the required element and its face using the 2017
ReferenceIntersector Class.

Create a collection of item ids Revit API in Python

So I am trying to use a list of input strings to isolate them in a view using Revit API. I got this far, but I am getting stuck where I am trying to create a set that takes all elements in a view and removes ones that are created from input IDs. I am doing this to end up with a set of all elements except ones that i want to isolate.
dataEnteringNode = IN0
view = IN0
str_ids = IN1
doc = __doc__
collector = FilteredElementCollector(doc, view.Id)
for i in str_ids:
int_id = int(i)
id = ElementId(int_id)
element = doc.GetElement(id)
element_set = ElementSet()
element_set.Insert(element)
elements_to_hide = collector.WhereElementIsNotElementType().Excluding(element_set).ToElements()
#Assign your output to the OUT variable
OUT = elements_to_hide
I would greatly appreciate a help in solving this error. I am getting that "expected ICollection[ElementId], got set". I am guessing the problem lies in a Excluding filter where i need to create a collection of Ids to exclude but I dont know how. Thank you in advance. Thank you for help in advance!
The reason your code doesn't work is that ElementSet in the Revit API does not implement the ICollection<T> interface - just the IEnumerable<T>. So, to get your code working, you will need to create an ICollection<T> object from your set.
Try something like this:
# ...
from System.Collections.Generic import List
element_collection = List[ElementId](element_set)
elements_to_hide = collector.WhereElementIsNotElementType().Excluding(element_collection).ToElements()

Search in new Sitecore ContentSearch using whole words

I am using new Sitecore search, and the issue I ran into is having results come for words that have nothing to do with my search term.
For example, searching for "lies" will find "applies". And this is not what I am looking for.
This is an example of search I am doing (simplified). It is a direct LINQ check for "Contains" on the "Content" property of the SearchResultItem, and most likely not what I supposed to do. It is just happen to be that samples I find online are practically doing so.
Example of my code (simplified). In here I break down the search sentence to separate keywords. By the way, I am looking for a way to show full sentence match first.
using (var context = ContentSearchManager.GetIndex("sitecore_web_index").CreateSearchContext())
{
var results = context.GetQueryable<SearchResultItem>()
.Filter(i => i.Path.StartsWith(Home.Paths.FullPath))
.Filter(GetTermPredicate(Term));
// use results here
}
protected Expression<Func<SearchResultItem, bool>> GetTermPredicate(string term)
{
var predicate = PredicateBuilder.True<SearchResultItem>();
foreach (var tempTerm in term.Split(' '))
{
predicate = predicate.And(p => p.Content.Contains(tempTerm));
}
return predicate;
}
Thank you in advance!!
All right. I got help from Sitecore Support.
In my version of Sitecore I can use the following to acheive search for a whole word instead of partial:
instead of:
predicate = predicate.And(p => p.Content.Contains(tempTerm));
use
predicate = predicate.And(p => p.Content.Equals(tempTerm));
Issue solved.
Replace Filter in your code by Where, it should be fine,
here is an example :
var currentIndex = ContentSearchManager.GetIndex("sitecore_web_index");
using (var context = currentIndex.CreateSearchContext())
{
var predicate = PredicateBuilder.True();
foreach (var currentWord in term.Split(‘ ‘))
{
predicate = predicate.Or(x => x.Content.Contains(currentWord ));
}
var results = context.GetQueryable().Where(predicate).GetResults();
}
As Ahmed notes, you should use Where instead of Filter, since Filter has no effect on search rank. The classic use case for filters is to apply a facet chosen by the user without distorting the ordering of results, as would happen if you used a Where clause.
Filtering is similar to using Where to restrict the result list. Both methods will affect the result in the same
result list, but when you use a Filter the scoring/ranking of the search hits is not affected by the filters.
Developer's Guide to Item Buckets and Search
There's a good dicussion of when to use Filter on the Sitecore 7 team blog:
Making Good Part 4: Filters, Paging and I'm feeling lucky.
If you only want to search for whole words, you could prefix and postfix the searchterm with a space. Allthough this doesn't catch all situations.

Create Document Library using Client Object Model

Just a quick question, is it possible to create a Document Library using the Client Object Model in SharePoint 2010?
I know you can create lists etc. Am I right in saying that a Document Library is just a 'special' type of List?
How can I specify that the List I create will be a Document Library?
Any help will be appreciated
Thanks
Yes. You can specify the TemplateType for your List.
List of TemplateTypes
using (ClientContext clientCTX = new ClientContext(url))
{
ListCreationInformation lci = new ListCreationInformation();
lci.Description = "My own DocLib";
lci.Title = "Library";
lci.TemplateType = 101;
List newLib = clientCTX.Web.Lists.Add(lci);
clientCTX.Load(newLib);
clientCTX.ExecuteQuery();
}
You can also set the templatetype with the following code, which I think makes things clearer to new programmers:
lci.TemplateType = (int) ListTemplateType.DocumentLibrary;

Resources