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.Segment3d;
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.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();
	}

	/**
	 * Returns the longest segment between two components. The length of the longest segment is the maximum distance
	 * between the components.
	 *
	 * @param component1 the first component
	 * @param component2 the second component
	 * @return the longest segment between any points of two components
	 */
	private Segment3d getLongestSegment(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();

		Segment3d longestSegment = null;
		for (Triangle3d sourceTriangle : sourceMesh) {
			for (Triangle3d targetTriangle : targetMesh) {
				Segment3d potentialLongestSegment = getLongestSegment(sourceTriangle, targetTriangle);
				if (longestSegment == null || potentialLongestSegment.getLength() > longestSegment.getLength()) {
					longestSegment = potentialLongestSegment;
				}
			}
		}
		return longestSegment;
	}

	/**
	 * Returns the longest segment between two triangles.
	 *
	 * @param triangle1 the first triangle
	 * @param triangle2 the second triangle
	 * @return the longest segment between any points of two triangles
	 */
	private Segment3d getLongestSegment(Triangle3d triangle1, Triangle3d triangle2) {
		Segment3d longestSegment = null;
		for (Vector3d firstPoint : triangle1) {
			for (Vector3d secondPoint : triangle2) {
				double potentialDistance = firstPoint.distance(secondPoint);
				if (longestSegment == null || potentialDistance > longestSegment.getLength()) {
					longestSegment = Segment3d.create(firstPoint, secondPoint);
				}
			}
		}
		return longestSegment;
	}

	private Result distanceCheck(Component source, Component target, ResultFactory results) {
		Segment3d longestSegment = getLongestSegment(source, target);

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

		// 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(longestSegment.getStartPoint(), longestSegment.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