Solibri API - Code Example

DistanceVisualizationRule Example

This example shows how to develop a simple rule that visualizes the distance between two different components. User defines the checked components and the maximum smallest distance between them.

This example shows also how to develop a simple UI Definition for this rule where the rule UI allows user to filter the selected components and and input a maximum length parameter.

This example includes using the low-level TriangleIterator API for accessing the geometry inside components. TriangleIterator provides access to the triangles the geometry of the component consists of in SMC.

You can download the examples project from here.

Table of Contents

  • Implementing the Distance Visualization Rule Example
    • DistanceVisualizationRule.java
  • Implementing the UI Definition
    • DistanceVisualizationRuleUIDefinition.java
    • DistanceVisualizationRule.properties
  • Example visualization result

Implementing the Distance Visualization Rule Example

DistanceVisualizationRule.java

package com.solibri.smc.api.examples.beginner;

  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.List;

  import com.solibri.geometry.linearalgebra.Vector3d;
  import com.solibri.geometry.mesh.TriangleMesh;
  import com.solibri.geometry.primitive3d.Triangle3d;
  import com.solibri.smc.api.SMC;
  import com.solibri.smc.api.checking.DoubleParameter;
  import com.solibri.smc.api.checking.FilterParameter;
  import com.solibri.smc.api.checking.OneByOneRule;
  import com.solibri.smc.api.checking.Result;
  import com.solibri.smc.api.checking.ResultFactory;
  import com.solibri.smc.api.checking.RuleParameters;
  import com.solibri.smc.api.distance.Distance;
  import com.solibri.smc.api.filter.AABBIntersectionFilter;
  import com.solibri.smc.api.filter.ComponentFilter;
  import com.solibri.smc.api.model.Component;
  import com.solibri.smc.api.model.PropertyType;
  import com.solibri.smc.api.ui.UIContainer;
  import com.solibri.smc.api.visualization.VisualizationItem;

  /**
  * An example check that visualizes all the max distances of all component pairs in a
  * component set; each max distance comes from a pair of components in the component set.
  *
  * A max distance is calculated using the maximum distance between all the points
  * in a component pair.
  */
  public final class DistanceVisualizationRule extends OneByOneRule {

  /**
  * Retrieve the parameter creation handler, used to define parameters for
  * this rule.
  */
  private final RuleParameters params = RuleParameters.of(this);

  /**
  * Retrieve the default filter.
  * Every component that passes the filter is then forwarded to
  * the {@link OneByOneRule#check(Component, ResultFactory)} method.
  */
  final FilterParameter rpComponentFilter = this.getDefaultFilterParameter();

  final FilterParameter rpComponentFilter2 = params.createFilter("rpComponentFilter2");

  final DoubleParameter maximumDistance = params.createDouble("rpMaximumDistance", PropertyType.LENGTH);

  /**
  * Add the UI definition from class DistanceVisualizationRuleUIDefinition.
  */
  private final DistanceVisualizationRuleUIDefinition uiDefinition = new DistanceVisualizationRuleUIDefinition(this);

  @Override
  public Collection<Result> check(Component component, ResultFactory resultFactory) {

  // Search only for components that are in range of the maximumDistance parameter.
  double searchDistance = maximumDistance.getValue();
  ComponentFilter filter2 = rpComponentFilter2.getValue();
  ComponentFilter withinDistanceFilter =
  AABBIntersectionFilter.ofComponentBounds(component, searchDistance, searchDistance).and(filter2);
  Collection<Component> targets = SMC.getModel().getComponents(withinDistanceFilter);

  List<Result> results = new ArrayList<>();

  // Check each component separately.
  for (Component target : targets) {
  results.add(distanceCheck(component, target, resultFactory));
}

return results;
}

@Override
public UIContainer getParametersUIDefinition() {
return uiDefinition.getDefinitionContainer();
}

/**
* Calculates the maximum distance between two components.
*
* @param component1 the first component
* @param component2 the second component
* @return the maximum distance between any points of components
*/
private Distance maxDistance(Component component1, Component component2) {
/*
* The triangles in component's geometry can be looped with the TriangleMesh used as an Iterable of triangles.
*/
TriangleMesh sourceMesh = component1.getTriangleMesh();
TriangleMesh targetMesh = component2.getTriangleMesh();

Distance maxDistance = null;

for (Triangle3d sourceTriangle : sourceMesh) {
for (Triangle3d targetTriangle : targetMesh) {
Distance potentialDistance = maxDistance(sourceTriangle, targetTriangle);
if (maxDistance == null || potentialDistance.getLength() > maxDistance.getLength()) {
maxDistance = potentialDistance;
}
}
}

return maxDistance;
}

/**
* Calculates the maximum distance between two triangles.
* @param triangle1 the first triangle
* @param triangle2 the second triangle
* @return the maximum distance between any points of two triangles
*/
private Distance maxDistance(Triangle3d triangle1, Triangle3d triangle2) {
Distance maxDistance = null;
maxDistance = updateDistance(triangle1.getFirstPoint(), triangle2.getFirstPoint(), maxDistance);
maxDistance = updateDistance(triangle1.getFirstPoint(), triangle2.getSecondPoint(), maxDistance);
maxDistance = updateDistance(triangle1.getFirstPoint(), triangle2.getThirdPoint(), maxDistance);

maxDistance = updateDistance(triangle1.getSecondPoint(), triangle2.getFirstPoint(), maxDistance);
maxDistance = updateDistance(triangle1.getSecondPoint(), triangle2.getSecondPoint(), maxDistance);
maxDistance = updateDistance(triangle1.getSecondPoint(), triangle2.getThirdPoint(), maxDistance);

maxDistance = updateDistance(triangle1.getThirdPoint(), triangle2.getFirstPoint(), maxDistance);
maxDistance = updateDistance(triangle1.getThirdPoint(), triangle2.getSecondPoint(), maxDistance);
maxDistance = updateDistance(triangle1.getThirdPoint(), triangle2.getThirdPoint(), maxDistance);

return maxDistance;
}

/**
* A helper method for updating the Distance object for a given pair of points.
*
* @param firstPoint the first point
* @param secondPoint the second points
* @param maxDistance the current Distance instance
* @return the new Distance object
*/
private static Distance updateDistance(Vector3d firstPoint, Vector3d secondPoint, Distance maxDistance) {
double potentialDistance = firstPoint.distance(secondPoint);
if (maxDistance == null || potentialDistance > maxDistance.getLength()) {
maxDistance = new Distance(potentialDistance, firstPoint, secondPoint);
}
return maxDistance;
}

private Result distanceCheck(Component source, Component target, ResultFactory results) {
// Calculate the distance.
Distance distance = maxDistance(source, target);

String nameSource = source.getName();
String nameTarget = target.getName();
String distanceText = PropertyType.LENGTH.getFormat().format(distance);

// Create the result.
return results
.create(
nameSource + " " + nameTarget + " " + distanceText,
"Distance between " + nameSource + " " + nameTarget + " is " + distanceText)
.withInvolvedComponent(target)
.withVisualization(visualization -> {
// Create visualization using provided factory that can create dimensional lines.
List<VisualizationItem> dimensionLine = VisualizationItem
.createDimension(distance.getStartPoint(), distance.getEndPoint());
visualization.addVisualizationItems(dimensionLine);
visualization.addComponent(source, 0.5);
visualization.addComponent(target, 0.5);
});
}

}

Implementing the UI Definition

DistanceVisualizationRuleUIDefinition.java

package com.solibri.smc.api.examples.beginner;

  import com.solibri.smc.api.checking.RuleResources;
  import com.solibri.smc.api.ui.BorderType;
  import com.solibri.smc.api.ui.UIComponent;
  import com.solibri.smc.api.ui.UIContainer;
  import com.solibri.smc.api.ui.UIContainerVertical;
  import com.solibri.smc.api.ui.UILabel;
  import com.solibri.smc.api.ui.UIRuleParameter;

  /**
  * Class that provides the UI layout for the Distance Visualization Rule.
  * The UI consists of two component filters and one double valued parameter field for length.
  */
  class DistanceVisualizationRuleUIDefinition {

  /**
  * The distance visualization rule.
  */
  private final DistanceVisualizationRule distanceVisualizationRule;

  /**
  * The UI definition container.
  */
  private final UIContainer uiDefinition;

  /**
  * Basic constructor.
  *
  * @param distanceVisualizationRule the distance visualization rule
  */
  public DistanceVisualizationRuleUIDefinition(DistanceVisualizationRule distanceVisualizationRule) {
  this.distanceVisualizationRule = distanceVisualizationRule;
  this.uiDefinition = createUIDefinition();
}

/**
* Returns the UI definition of the Rule.
*
* @return the UI definition container of the Rule
*/
public UIContainer getDefinitionContainer() {
return uiDefinition;
}

private UIContainer createUIDefinition() {
/*
* Fetch the resources for this rule.
*/
RuleResources resources = RuleResources.of(distanceVisualizationRule);

/*
* Create the vertical component container.
*/
UIContainer uiContainer = UIContainerVertical.create(
resources.getString("UI.DistanceVisualizationRule.TITLE"),
BorderType.LINE);

/*
* Add the description.
*/
uiContainer
.addComponent(UILabel.create(resources.getString("UI.DistanceVisualizationRule.DESCRIPTION")));

/*
* Add the first filter for components to check.
*/
uiContainer.addComponent(createComponentFilterUIDefinition());

/*
* Add second filter for components to check.
*/
uiContainer.addComponent(createSecondComponentFilterUIDefinition());

/*
* Add third filter for the range of the secondary components.
*/
uiContainer.addComponent(createMaximumDistanceFilterUIDefinition());

return uiContainer;
}

private UIComponent createComponentFilterUIDefinition() {
UIContainer uiContainer = UIContainerVertical.create();
uiContainer.addComponent(UIRuleParameter.create(distanceVisualizationRule.rpComponentFilter));

return uiContainer;
}

private UIComponent createSecondComponentFilterUIDefinition() {
UIContainer uiContainer = UIContainerVertical.create();
uiContainer.addComponent(UIRuleParameter.create(distanceVisualizationRule.rpComponentFilter2));

return uiContainer;
}

private UIComponent createMaximumDistanceFilterUIDefinition() {
UIContainer uiContainer = UIContainerVertical.create();
uiContainer.addComponent(UIRuleParameter.create(distanceVisualizationRule.maximumDistance));

return uiContainer;
}
}

DistanceVisualizationRule.properties

DEFAULT_NAME=Maximum Distance Visualization Rule
  DEFAULT_DESCRIPTION=This rule visualizes the maximum distance between the components specified by the two filters.
  AUTHOR=Solibri, Inc.
  AUTHOR_TAG=SOL
  UID=EX3
  VERSION=1.0
  DATE=2018-12-13

  rpComponentFilter.NAME = Source Components
  rpComponentFilter.DESCRIPTION = This filter specifies the set of components to check.

  rpComponentFilter2.NAME = Target Components
  rpComponentFilter2.DESCRIPTION = This filter specifies the set of components to check.

  rpMaximumDistance.NAME = Maximum Distance
  rpMaximumDistance.DESCRIPTION = Maximum distance used to search the components near by.
  rpMaximumDistance.DEFAULT_VALUE=5m

  UI.DistanceVisualizationRule.TITLE = Distance Visualization Rule
  UI.DistanceVisualizationRule.DESCRIPTION = This rule visualizes the distance from the source components to the target components. The target components must be found near the sources.

Example visualization result