Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

String parameter filtering is retrieving false data

13 REPLIES 13
SOLVED
Reply
Message 1 of 14
ameer.mansourWAK8Y
1129 Views, 13 Replies

String parameter filtering is retrieving false data

Hi 

I am trying to filter walls based on "Fire Rating" parameter but it retrieves walls that the rule satisfies plus walls that don't contain that parameter!
so how can it ignore walls that don't contain that parameter!?

ParameterValueProvider provider = new ParameterValueProvider(new ElementId((int)BuiltInParameter.FIRE_RATING)); 
FilterStringRule rule1 = new FilterStringRule(provider, new FilterStringContains(), @"/", false);
ElementParameterFilter filter1 = new ElementParameterFilter(rule1);
var MyWalls=(new FilteredElementCollector(doc))
.OfCategory(BuiltInCategory.OST_Walls)
.WherePasses(filter1)
.ToElementIds();

 

13 REPLIES 13
Message 2 of 14

Can you please provide a minimal reproducible case for the development team and others to analyse?

 

https://thebuildingcoder.typepad.com/blog/about-the-author.html#1b

 

Thank you!

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 3 of 14

Hi @jeremytammik,

I sent a message to you having the reproducible case attached.

Please let me know when you receive it.

Message 4 of 14

I received the sample model and am looking at it now.

 

Jeremy Tammik, Developer Advocacy and Support, The Building Coder, Autodesk Developer Network, ADN Open
Message 5 of 14

Dear Ameer,

 

Thank you for your nice clean reproducible case.

 

I can reproduce the behaviour you describe and find it rather weird as well, so I submitted it to the development team for further analysis.

 

I logged the issue REVIT-172990 [Parameter filter with FilterStringContains returns false positive] with our development team for this on your behalf as it requires further exploration and possibly a modification to our software. Please make a note of this number for future reference.

 

You are welcome to request an update on the status of this issue or to provide additional information on it at any time quoting this change request number.

 

This issue is important to me. What can I do to help?

 

This issue needs to be assessed by our engineering team and prioritised against all other outstanding change requests. Any information that you can provide to influence this assessment will help. Please provide the following where possible:

 

  • Impact on your application and/or your development.
  • The number of users affected.
  • The potential revenue impact to you.
  • The potential revenue impact to Autodesk.
  • Realistic timescale over which a fix would help you.
  • In the case of a request for a new feature or a feature enhancement, please also provide detailed Use cases for the workflows that this change would address.

 

This information is extremely important. Our engineering team have limited resources, and so must focus their efforts on the highest impact items. We do understand that this will cause you delays and affect your development planning, and we appreciate your cooperation and patience.

 

I cleaned up your code and submitted it in the following form as TestFilterStringContains:

   

  public void TestFilterStringContains( Document doc )
  {
    BuiltInParameter bip = BuiltInParameter.FIRE_RATING;

    ElementId pid = new ElementId( bip );

    ParameterValueProvider provider
      = new ParameterValueProvider( pid );

    FilterStringRuleEvaluator evaluator 
      = new FilterStringContains();

    FilterStringRule rule = new FilterStringRule( 
      provider, evaluator, "/", false );

    ElementParameterFilter filter 
      = new ElementParameterFilter( rule );

    var myWalls = new FilteredElementCollector( doc )
      .OfCategory( BuiltInCategory.OST_Walls )
      .WherePasses( filter );

    List<ElementId> false_positive_ids 
      = new List<ElementId>();

    foreach( Element wall in myWalls )
    {
      Parameter param = wall.get_Parameter( bip );
      if( null == param )
      {
        false_positive_ids.Add( wall.Id );
      }
    }
    string s = string.Join( ", ", 
      false_positive_ids.Select<ElementId, string>( 
        id => id.IntegerValue.ToString() ) );

    TaskDialog dlg = new TaskDialog( "False Positives" );
    dlg.MainInstruction = "False filtered walls ids: ";
    dlg.MainContent = s;
    dlg.Show();
  }

  

It displays a message like this in your sample model:

 

result_message.png

 

      

You might be able to achieve the desired result by combining the FilterStringContains evaluator with other rules and filters.

 

For instance, you may be able to add something like 'is not empty' in addition to 'contains'.

 

I hope this helps.

 

Best regards,

 

Jeremy

 

Jeremy Tammik, Developer Advocacy and Support, The Building Coder, Autodesk Developer Network, ADN Open
Message 6 of 14

Dear Ameer,

 

Thank you for your patience.

 

The development team analysed your reproducible case in the issue REVIT-172990 [Parameter filter with FilterStringContains returns false positive] that I logged for you and found the reason for this behaviour.

 

If the internal method ParameterValueProvider::getParameterValue() cannot get the parameter from the element itself, will also try to get it from the element's type:

   

  if (m_elemOrSymbol == EOS_Symbol
    || err != ERR_SUCCESS || !oParameterValue)
  {
    ElementId typeId = pElement->getTypeId();
    if (validElementId(typeId))
    {
      const Element *pTypeElement
        = pElement->getDocument()->getElement(typeId);
        
      if (pTypeElement != NULL)
      {
        oParameterValue = pTypeElement->getParameterValue(
          m_parameter);
          
        err = getErrFromParameterValue(oParameterValue);
        if (err != ERR_SUCCESS)
        {
          return nullptr;
        }
      }
    }
  }

   

Therefore, yes, you cannot find the parameter in the walls.

 

However, you can find the parameters in their wall type!

 

That's why you can still get those walls.

 

This behaviour has been in effect for a long time, so we should not think about changing it.

 

However, if the documentation and knowledge base does not mention this behaviour, this information must be added.

 

We therefore closed REVIT-172990 [Parameter filter with FilterStringContains returns false positive] and raised a new issue REVIT-173253 [Parameter filter with FilterStringContains returns false positive] for the documentation team to document this behaviour. Please make a note of this number for future reference.

 

I hope this clarifies.

 

Best regards,

 

Jeremy

 

Jeremy Tammik, Developer Advocacy and Support, The Building Coder, Autodesk Developer Network, ADN Open
Message 7 of 14

Hi @jeremy_tammik 

Thanks!

I am going to accept your reply as an accepted answer but it is not as expected.

If you have time, check my following questions:
1-  


Therefore, yes, you cannot find the parameter in the walls.

 

However, you can find the parameters in their wall type!


I think this behaviour is not acceptable logically even though it was in effect for a long time. at least it should return the wall type itself rather than returning all walls under that type.

2- can it be modified to have a boolean to search through the element's type or not? or like the element collection i.e. WhereElementIsElementType / WhereElementIsNotElementType

FilteredElementCollector collector = new FilteredElementCollector(doc);
            collector.WhereElementIsNotElementType()
Message 8 of 14

I agree that this behaviour defeats part of the purpose of the parameter filter.

 

If I were you, I would choose the simple solution of filtering for parameters that are guaranteed not to be present on the type.

 

Jeremy Tammik, Developer Advocacy and Support, The Building Coder, Autodesk Developer Network, ADN Open
Message 9 of 14

I always preferred the functionality as it is now. There are various solutions out there for finding elements that rely on not having to separately look through the parameters on the type or know that a parameter is on a type or an instance.

 

Imagine you want to find all instances that have a certain type parameter, you would first have to filter for all types, filter those for the parameter match, then filter again for all instances that are of one of those types. This is already a common approach for a lot of cases where parameter filters can’t be used.

 

I thought it just saved a lot of work really, I see no need for a change. If you want to know the parameter is on the instance then put the results through a further filter. You can supply a list of ids to a further element filter at any time. If you want to know parameter is on the type, filter first for types. In general, I don’t see much use of Logical AND/OR Filters sometimes I wonder if their existence is known of? People seem to have other methods but again use: LogicalAndFilter with

ParameterElementFilter & ElementIsElementTypeFilter(Inverted = True)

 

ElementParmeterFilter is a slow filter so first should use other quick filter before it.

 

How it is working is how it works in the UI when you set up visibility filters i.e. there is no distinction between type and instance parameters there. I imagine this is the internal system that this filter class leverages.

Message 10 of 14
RPTHOMAS108
in reply to: RPTHOMAS108

When I consider further there is a bit of a hole in functionality there.

 

Since you are forced to get a list of elements and then rule out those that have a type parameter match not an instance parameter match i.e. there are four cases:

 

Parameter with matching name and value is on: Type, Instance, Both, Neither.

We can only find with filter that it is on: Either or Neither

 

So how would we find Elements with only a matching parameter on the Instance is the question? After filtering with ElementParameterFilter we would have to manually check via Linq perhaps. We only care that it is or isn't on the instance so that could simplify things.

 

Message 11 of 14
jeremy_tammik
in reply to: RPTHOMAS108

Exactly what I meant by saying, defeats part of the purpose.

 

Thank you for fleshing it out in more detail.

 

Linq is super slow compared to the built-in parameter filter, and I see no other option to achieve the in-between distinctions.

 

Jeremy Tammik, Developer Advocacy and Support, The Building Coder, Autodesk Developer Network, ADN Open
Message 12 of 14
FAIR59
in reply to: jeremy_tammik

I noticed the same behavior for the Parameter properties of an Element. Getting a parameter on an (family)instance  by GUID or Definition also returns the type-parameter. 

FAIR59_0-1612006333410.png

please update the documentation for these properties.

Message 13 of 14
jeremy_tammik
in reply to: FAIR59

Wow!

 

I assume that your note implies:

 

> Getting a parameter on an (family)instance  by GUID or Definition also returns the type-parameter...

 

  • IF the requested parameter is not present on the instance itself
  • AND the requested parameter is present on the family symbol/type.

 

Thank you very much for the information!

 

Again, I would suggest that the safest way to handle this behaviour is to ensure that all parameters of interest are defined either on the instance or the type, and not on both.

   

Jeremy Tammik, Developer Advocacy and Support, The Building Coder, Autodesk Developer Network, ADN Open
Message 14 of 14
jeremy_tammik
in reply to: FAIR59

I added your note to the blog post as well:

 

https://thebuildingcoder.typepad.com/blog/2021/01/parameter-filter-checking-element-type-and-ocr.htm...

 

Thank you for the info!

  

Jeremy Tammik, Developer Advocacy and Support, The Building Coder, Autodesk Developer Network, ADN Open

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community