Skip to content
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

Alb999 rail alignment value constraints #37

Draft
wants to merge 24 commits into
base: main
Choose a base branch
from

Conversation

aothms
Copy link
Collaborator

@aothms aothms commented Jan 22, 2023

Rule implementation

An IfcAlignmentHorizontal shall only nest a list of IfcAlignmentHorizontalSegment (through IfcAlignmentSegment) that has PredefinedType set to LINE, CIRCULARARC or CLOTHOID.

NB The validation service validates requirements that are universally true and not organization or context-specific. For that purpose:

  • This rule still needs to be updated to be universally true, with
    • context-specific requirements encoded in IDS (this is possible because the non-rooted entity IfcAlignmentHorizontal can be selected with an attribute constraint on PredefinedType)
    • the rule remainig universal but individual stakeholders "forking" the repository to make organization-specific adaptations
  • (or) the rule will remain just an example and will not be merged to the main branch (but can still be invoked through the "sandbox" functionality)

Considering the following example instantiation diagram

alig dot

the feature has been annotated with the context (name of instance) being operated on in square brackets ([ ... ])

@implementer-agreement
@ALB
Feature: Rail Alignment value constraints

  Background: Rail alignment
  
[AL1, AL2]           Given An IfcAlignment
[AL1]                And A relationship IfcRelReferencedInSpatialStructure to IfcAlignment from IfcRail
    
  Scenario: Agreement on allowed values for horizontal segment types
    
[AL1_H]              Given A relationship IfcRelNests from IfcAlignment to IfcAlignmentHorizontal and following that
[AL1_H_S1, AL1_H_S2] Given A relationship IfcRelNests from IfcAlignmentHorizontal to IfcAlignmentSegment and following that
[..., ...]           Given Its attribute DesignParameters
[LINE, HELMERTCURVE] Given Its attribute PredefinedType
    
[raises error        Then the value must be "LINE" or "CIRCULARARC" or "CLOTHOID"
on HELMERTCURVE]

The current validation report for a population model like this is according to:

Rail Alignment value constraints/Agreement on allowed values for horizontal segment types.v1
• the value must be "LINE" or "CIRCULARARC" or "CLOTHOID"
The value 'HELMERTCURVE' on #40=IfcAlignmentHorizontalSegment('17KlfolOr6ReLWMUjUKk$j',$,$,$,$,$,$,$,.HELMERTCURVE.) is not one of 'LINE', 'CIRCULARARC', 'CLOTHOID'

In principal the entire history of "stack frames" is available when building the report so we can recover the full path from alignment to segment type.

Background: Rail alignment

This rule uses the background statement, which is functionally equivalent to having the same given statements prepended to each of the scenarios, but offers additional advantages later in categorizing such rules based on their background. We might be referring to this background selection as an "activation mechanism", i.e a graph pattern (in this case) that triggers validation constraints to become applicable.

to/from

A relationship IfcRelReferencedInSpatialStructure to IfcAlignment from IfcRail
                                                  ^^

to refers to the Relating(Object/...) side of the relationship node

to and from can be positioned arbitrarily but the convention is that the first end of the relationship should correspond to the previously established context.

corresponding nodes to build a graph

Given An IfcAlignment
         ^^^^^^^^^^^^
  And A relationship IfcRelReferencedInSpatialStructure to IfcAlignment from IfcRail
                                                           ^^^^^^^^^^^^

The first part of the relationship definition should correspond to the previously established context

traversal

Given An IfcAlignment
         ^^^^^^^^^^^^
  And A relationship IfcRelReferencedInSpatialStructure to IfcAlignment from IfcRail
                                                           ^^^^^^^^^^^^
...

Given A relationship IfcRelNests from IfcAlignment to IfcAlignmentHorizontal and following that
                                      ^^^^^^^^^^^^

In the first case the context stays on alignment, so it gets repeated in the third statement.

Given A relationship IfcRelNests from IfcAlignment to IfcAlignmentHorizontal and following that
                                                                             ^^^^^^^^^^^^^^^^^^
Given A relationship IfcRelNests from IfcAlignmentHorizontal to IfcAlignmentSegment and following that

However with the and following that clause we cause the context to switch to IfcAlignmentHorizontal (in this case).

@aothms aothms marked this pull request as draft January 22, 2023 14:07
@aothms
Copy link
Collaborator Author

aothms commented Jan 22, 2023

Sandbox ok ca8bf07

@aothms
Copy link
Collaborator Author

aothms commented Jan 22, 2023

Sandbox ok c3b4a2c

@aothms
Copy link
Collaborator Author

aothms commented Jan 22, 2023

Sandbox ok e2d5cfa

Copy link
Contributor

@pjanck pjanck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initial comments for Gherkin.

Comment on lines +12 to +15
Given A relationship IfcRelNests from IfcAlignment to IfcAlignmentHorizontal and following that
Given A relationship IfcRelNests from IfcAlignmentHorizontal to IfcAlignmentSegment and following that
Given Its attribute DesignParameters
Given Its attribute PredefinedType
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you meant And in the last three lines? Or are all four conditions to be interpreted independently of one another?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no functional difference between that. and is just a shortcut for the previously used gherkin keyword. But I agree it should be used consistently (maybe it's actually clearer to never use and).

And An IfcElement
And A relationship IfcRelAggregates from IfcElement to IfcElement
Then The relative placement of that IfcElement must be provided by an IfcLocalPlacement entity
And The PlacementRelTo attribute must point to the IfcLocalPlacement of the container element established with IfcRelAggregates relationship
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the container is placed by IfcGridPlacement? As the sentence reads right now, it is not allowed for IfcRelAggregates.RelatingObject to ever be placed by anything else as IfcLocalPlacement.

Comment on lines +12 to +13
Given A relationship IfcRelNests from IfcAlignment to IfcAlignmentHorizontal and following that
Given A relationship IfcRelNests from IfcAlignmentHorizontal to IfcAlignmentSegment and following that
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is and following that?

Copy link
Collaborator Author

@aothms aothms Jan 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question, I've updated the PR description. You can find the answer under "traversal". In short it means that, in the first case without and following that the a relationship ... statement checks whether such a relationship exists, but keeps the context on the previously active node (alignment). In the second case we actually descend according to the nesting structure, so that the attribute DesignParameters is read from the IfcAlignmentSegment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes a lot of sense, nice to see that this approach is useful for more rules (also referring to your explanation in the top of this PR). For the 0.6 sprint we are encountering a rule (briefly discussed in a previous meeting) for which we will need attributes for both the previously activate node and the following elements. That seems to be possible this way. Or maybe we will need to make it more explicit.

Comment on lines +9 to +10
And A relationship IfcRelAggregates from IfcElement to IfcElement
Then The relative placement of that IfcElement must be provided by an IfcLocalPlacement entity
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which that does this sentence refer to? In the sentence above, there are two IfcElements ...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not going to reply here, this feature shows up here, because my PR was based on two un-merged PRs. See #27.

Comment on lines +12 to +13
Given A relationship IfcRelNests from IfcAlignment to IfcAlignmentHorizontal and following that
Given A relationship IfcRelNests from IfcAlignmentHorizontal to IfcAlignmentSegment and following that
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes a lot of sense, nice to see that this approach is useful for more rules (also referring to your explanation in the top of this PR). For the 0.6 sprint we are encountering a rule (briefly discussed in a previous meeting) for which we will need attributes for both the previously activate node and the following elements. That seems to be possible this way. Or maybe we will need to make it more explicit.

Comment on lines +473 to +480

if constraint in ('identical', 'unique'):

for i, values in enumerate(instances):
if not values:
continue

msg = value_error_msg(identical_or_unique=constraint, attribute=getattr(context, 'attribute', 'None'))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it okay for you to convert this draft PR to an actual PR (without merging it)? I would like to test where the code is failing for the open PRs, but cannot git checkout in a branch for this PR.
Or is there no branch for this PR?

Comment on lines +21 to +24
register_type(from_to=TypeBuilder.make_enum({"from": 0, "to": 1 }))
register_type(maybe_and_following_that=TypeBuilder.make_enum({"": 0, "and following that": 1 }))


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It computes a regular expression pattern for the given enumeration of words/strings and stores them in X.pattern attribute.

That is very useful

@given('A relationship {relationship} {dir1:from_to} {entity} {dir2:from_to} {other_entity}')
@given('A relationship {relationship} {dir1:from_to} {entity} {dir2:from_to} {other_entity} {tail:maybe_and_following_that}')
def step_impl(context, relationship, dir1, entity, dir2, other_entity, tail=0):
assert dir1 != dir2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice implementation :-) Is it an idea to also assert it is in the right direction? I would think if someone working on this would break the convention you were describing, it would return an empty list context.instances, resulting in a false positive. I can imagine it would help with debugging for someone writing a rule, but perhaps the effort is greater than the benefit in this.

@aothms
Copy link
Collaborator Author

aothms commented Jan 25, 2023

Sandbox ok 08ae8d6

@aothms
Copy link
Collaborator Author

aothms commented Jan 27, 2023

Sandbox ok 45690e3

@aothms
Copy link
Collaborator Author

aothms commented Jan 27, 2023

Sandbox ok 427fbf0

Comment on lines 5 to +9
def before_feature(context, feature):
# @tfk we have this strange issue between stack frames blending over
# between features so we need to preserve only the bottom two stack
# frames when beginning a new feature.
context._stack = context._stack[-2:]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aah, that explains it .. I tried to add context._push() with at the 'Its values' statement to retrieve it later and run into exactly this (another feature somehow not working anymore ..).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants