| // ***************************************************************************** |
| // Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // which accompanies this distribution, and is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // Contributors: |
| // Pierre Allard - initial API and implementation |
| // Regent L'Archeveque |
| // Sebastien Gemme |
| // |
| // SPDX-License-Identifier: EPL-1.0 |
| // ***************************************************************************** |
| |
| |
| @GenModel(prefix="ApogyCommonTopology", |
| childCreationExtenders="true", |
| extensibleProviderFactory="true", |
| multipleEditorPages="false", |
| copyrightText="******************************************************************************* |
| Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency |
| All rights reserved. This program and the accompanying materials |
| are made available under the terms of the Eclipse Public License v1.0 |
| which accompanies this distribution, and is available at |
| http://www.eclipse.org/legal/epl-v10.html |
| |
| Contributors: |
| Pierre Allard - initial API and implementation |
| Regent L'Archeveque, |
| Sebastien Gemme |
| |
| SPDX-License-Identifier: EPL-1.0 |
| *******************************************************************************", |
| modelName="ApogyCommonTopology", |
| suppressGenModelAnnotations="false") |
| @GenModel(dynamicTemplates="true", templateDirectory="platform:/plugin/org.eclipse.apogy.common.emf.codegen/templates") |
| @GenModel(modelDirectory="/org.eclipse.apogy.common.topology/src-gen") |
| @GenModel(editDirectory="/org.eclipse.apogy.common.topology.edit/src-gen") |
| |
| package org.eclipse.apogy.common.topology |
| |
| import org.eclipse.apogy.common.emf.IFilter |
| import org.eclipse.apogy.common.emf.CompositeFilter |
| import org.eclipse.apogy.common.math.Tuple3d |
| import org.eclipse.apogy.common.math.Matrix3x3 |
| import org.eclipse.apogy.common.Apogy |
| |
| // Types |
| |
| type Matrix4d wraps javax.vecmath.Matrix4d |
| type EClass wraps org.eclipse.emf.ecore.EClass |
| type INodeVisitor wraps org.eclipse.apogy.common.topology.INodeVisitor |
| type Collection<T> wraps java.util.Collection |
| type List<T> wraps java.util.List |
| |
| /** |
| * Defines a provider of topology. |
| */ |
| interface TopologyProvider |
| { |
| refers readonly GroupNode topologyRoot |
| } |
| |
| /** |
| * The base class of all nodes in a topology. |
| */ |
| @Apogy(hasCustomClass="true") |
| abstract class Node |
| { |
| /** |
| * The parent of the node. |
| */ |
| @GenModel(notify="true", propertyCategory="NODE") |
| refers Node parent |
| |
| /** |
| * The description of the node. |
| */ |
| @GenModel(notify="true", propertyCategory="NODE") |
| String description |
| |
| /** |
| * The node identifier. |
| */ |
| @GenModel(notify="true", propertyCategory="NODE") |
| String nodeId |
| |
| /** |
| * Accepts a Node visitor. This is done so that the visitor pattern as a way to explore or process a topology. |
| * @param visitor The node visitor. |
| * @see https://en.wikipedia.org/wiki/Visitor_pattern |
| */ |
| op void accept(INodeVisitor visitor) |
| } |
| |
| /** |
| * A node that refers to another node without containing it. |
| */ |
| @Apogy(hasCustomClass="true") |
| class Link extends Node |
| { |
| /** |
| * The node being referred to. |
| */ |
| refers Node node |
| } |
| |
| /** |
| * A node that has no children. |
| */ |
| class Leaf extends Node |
| { |
| } |
| |
| /** |
| * A node that refers to a file where geometry is stored. |
| */ |
| @Apogy(hasCustomItemProvider="true") |
| class URLNode extends Leaf |
| { |
| /** |
| * URL string referring to the resource containing the geometry. |
| */ |
| String url |
| |
| /** |
| * The number of polygons loaded from the url. |
| */ |
| @GenModel(notify="true", property="Readonly") |
| int polygonCount |
| |
| /** |
| * The number of vertices loaded from the url. |
| */ |
| @GenModel(notify="true", property="Readonly") |
| int vertexCount |
| } |
| |
| /** |
| * A node that exposes generic data. This data is typically not a Node. |
| */ |
| @Apogy(hasCustomItemProvider="true") |
| class ContentNode<T> extends Leaf |
| { |
| /** |
| * The node's content. |
| */ |
| contains T content |
| } |
| |
| /** |
| * A Content Node that refers the data it exposes. |
| */ |
| @Apogy(hasCustomClass="true", hasCustomItemProvider="true") |
| class ReferencedContentNode<T> extends ContentNode<T> |
| { |
| /** |
| * The node's referred content. |
| */ |
| refers T referencedContent |
| } |
| |
| /** |
| * A Content Node that contains the data it exposes. |
| */ |
| @Apogy(hasCustomClass="true", hasCustomItemProvider="true") |
| class AggregateContentNode<T> extends ContentNode<T> |
| { |
| /** |
| * The content contained in this node. |
| */ |
| contains T aggregateContent |
| } |
| |
| /** |
| * Super class of all node that refers/contain children nodes. |
| */ |
| class GroupNode extends Node |
| { |
| /** |
| * The list of children of this Node. |
| */ |
| @GenModel(children="false", createChild="false") |
| contains Node [0..*] children |
| } |
| |
| /** |
| * A GroupNode that refers to its child nodes. |
| */ |
| @Apogy(hasCustomClass="true", hasCustomItemProvider="true") |
| class ReferencedGroupNode extends GroupNode |
| { |
| /** |
| * List of referred children Nodes. |
| */ |
| @GenModel(children="true", createChild="false") |
| refers Node [0..*] referencedChildren |
| } |
| |
| /** |
| * A GroupNode that contains its child nodes. |
| */ |
| @Apogy(hasCustomClass="true", hasCustomItemProvider="true") |
| class AggregateGroupNode extends GroupNode |
| { |
| /** |
| * List of contained children Nodes. |
| */ |
| @GenModel(children="true", createChild="true") |
| contains Node [0..*] aggregatedChildren |
| } |
| |
| /** |
| * An Aggregate Group Node that contains position information. |
| */ |
| @Apogy(hasCustomClass="true", hasCustomItemProvider="true") |
| class PositionNode extends AggregateGroupNode |
| { |
| /** |
| * The position. |
| */ |
| @GenModel(children="false", createChild="false") |
| contains Tuple3d position |
| } |
| |
| /** |
| * An Aggregate Group Node that contains orientation information. |
| */ |
| @Apogy(hasCustomClass="true", hasCustomItemProvider="true") |
| class RotationNode extends AggregateGroupNode |
| { |
| /** |
| * The orientation, in the form of a rotation matrix. |
| */ |
| @GenModel(children="false", createChild="false") |
| contains Matrix3x3 rotationMatrix |
| } |
| |
| /** |
| * An Aggregate Group Node that contains both position and orientation information. |
| */ |
| @Apogy(hasCustomClass="true", hasCustomItemProvider="true") |
| class TransformNode extends PositionNode, RotationNode |
| { |
| /** |
| * Returns the node pose as a 4x4 affine transformation matrix. |
| */ |
| op Matrix4d asMatrix4d() |
| |
| /** |
| * Sets this node pose from an 4x4 affine transformation matrix |
| */ |
| op void setTransformation(Matrix4d matrix) |
| } |
| |
| |
| class PickAndPlaceNode extends TransformNode |
| { |
| } |
| |
| /** |
| * Class representing a node path in a topology. Node are referred to by their nodeID. |
| */ |
| class NodePath |
| { |
| /** |
| * The list of nodeID, from root to end. |
| */ |
| String[0..*] nodeIds |
| } |
| |
| |
| /** |
| * Represent a viewpoint in the 3D world. |
| */ |
| @Apogy(hasCustomClass="true") |
| abstract class AbstractViewPoint |
| { |
| /* |
| * The name of the ViewPoint |
| */ |
| String name |
| |
| /** |
| * The position of the view point. |
| */ |
| @GenModel(children="false", createChild="false") |
| contains Tuple3d position |
| |
| /** |
| * The orientation of the view point. |
| */ |
| @Apogy(units="rad") |
| contains Matrix3x3 rotationMatrix |
| |
| /** |
| * Initialize the view point for a given topology. |
| * @param root The root of the topology that the view point will be used in. |
| */ |
| op void initialize(Node root) |
| } |
| |
| /** |
| * A reference to an AbstractViewPoint. |
| */ |
| class AbstractViewPointReference |
| { |
| /** |
| * The AbstractViewPoint. |
| */ |
| refers AbstractViewPoint abstractViewPoint |
| } |
| |
| /** |
| * Specialized case of AbstractViewPoint that represent an arbitrary view point that can be moved around in the 3D world. |
| */ |
| @Apogy(hasCustomItemProvider="true") |
| class ArbitraryViewPoint extends AbstractViewPoint |
| { |
| } |
| |
| /** |
| * Specialized case of AbstractViewPoint that represent a view point which position and orientation are attached to a node in the topology. |
| */ |
| @Apogy(hasCustomClass="true", hasCustomItemProvider="true") |
| class AttachedViewPoint extends AbstractViewPoint |
| { |
| /** |
| * Whether or not translation relative to this point attachment Node is enabled. |
| */ |
| boolean allowTranslation = "false" |
| |
| /** |
| * Whether or not rotation relative to this point attachment Node is enabled. |
| */ |
| boolean allowRotation = "false" |
| |
| /** |
| * The node to which the view point is attached. |
| */ |
| refers transient volatile readonly Node node |
| |
| /** |
| * A node path referring to the node. |
| */ |
| contains NodePath nodePath |
| } |
| |
| /** |
| * Facade for Topology. |
| */ |
| @Apogy(isSingleton="true", hasCustomClass="true") |
| class ApogyCommonTopologyFacade |
| { |
| /** |
| * Creates a Link node that point to a specified Node. |
| * @param node The node the Link point to. |
| * @return The Link node created. |
| */ |
| op Link createLink(Node node) |
| |
| /** |
| * Creates a ContentNode that contains a specified content. |
| * @param content The content of the node. |
| * @return The ContentNode created. |
| */ |
| op <T> ContentNode<T> createContentNode(T content) |
| |
| /** |
| * Creates a ReferencedContentNode that refers to a specified content. |
| * @param content The content the node is to refer to. |
| * @return The ReferencedContentNode created. |
| */ |
| op <T> ReferencedContentNode<T> createReferencedContentNode(T content) |
| |
| /** |
| * Creates a AggregateContentNode that contains a specified content. |
| * @param content The content of the node. |
| * @return The AggregateContentNode created. |
| */ |
| op <T> AggregateContentNode<T> createAggregateContentNode(T content) |
| |
| /** |
| * Creates a PositionNode with x,y,and z coordinates. |
| * @param x the position along the x axis, in meters. |
| * @param y the position along the y axis, in meters. |
| * @param z the position along the z axis, in meters. |
| */ |
| op PositionNode createPositionNode(@Apogy(units="m") double x, @Apogy(units="m") double y, @Apogy(units="m")double z) |
| |
| /** |
| * Creates a rotation node with the rotation order x*y*z. |
| * @param rx The rotation around the x axis, in radians. |
| * @param ry The rotation around the y axis, in radians. |
| * @param rz The rotation around the z axis, in radians. |
| */ |
| op RotationNode createRotationNodeXYZ(@Apogy(units="rad") double rx, @Apogy(units="rad") double ry, @Apogy(units="rad") double rz) |
| |
| /** |
| * Creates a rotation node with the rotation order y*z*x. |
| * @param rx The rotation around the x axis, in radians. |
| * @param ry The rotation around the y axis, in radians. |
| * @param rz The rotation around the z axis, in radians. |
| */ |
| op RotationNode createRotationNodeYZX(@Apogy(units="rad") double rx, @Apogy(units="rad") double ry, @Apogy(units="rad") double rz) |
| |
| /** |
| * Creates a rotation node with the rotation order z*y*x. |
| * @param rx The rotation around the x axis, in radians. |
| * @param ry The rotation around the y axis, in radians. |
| * @param rz The rotation around the z axis, in radians. |
| */ |
| op RotationNode createRotationNodeZYX(@Apogy(units="rad") double rx, @Apogy(units="rad") double ry, @Apogy(units="rad") double rz) |
| |
| /** |
| * Creates a transformation node with the rotation order x*y*z. |
| * @param tx The x translation, in meters. |
| * @param ty The y translation, in meters. |
| * @param tz The z translation, in meters. |
| * @param rx The rotation around the x axis, in radians. |
| * @param ry The rotation around the y axis, in radians. |
| * @param rz The rotation around the z axis, in radians. |
| */ |
| op TransformNode createTransformNodeXYZ(@Apogy(units="m")double tx, @Apogy(units="m")double ty, @Apogy(units="rad") double tz, @Apogy(units="m") double rx, @Apogy(units="rad") double ry, @Apogy(units="rad") double rz) |
| |
| /** |
| * Creates a transformation node with the rotation order y*z*x. |
| * @param tx The x translation, in meters. |
| * @param ty The y translation, in meters. |
| * @param tz The z translation, in meters. |
| * @param rx The rotation around the x axis, in radians. |
| * @param ry The rotation around the y axis, in radians. |
| * @param rz The rotation around the z axis, in radians. |
| */ |
| op TransformNode createTransformNodeYZX(@Apogy(units="m")double tx, @Apogy(units="m")double ty, @Apogy(units="rad") double tz, @Apogy(units="m") double rx, @Apogy(units="rad") double ry, @Apogy(units="rad") double rz) |
| |
| /** |
| * Creates a transformation node with the rotation order z*y*x. |
| * @param tx The x translation, in meters. |
| * @param ty The y translation, in meters. |
| * @param tz The z translation, in meters. |
| * @param rx The rotation around the x axis, in radians. |
| * @param ry The rotation around the y axis, in radians. |
| * @param rz The rotation around the z axis, in radians. |
| */ |
| op TransformNode createTransformNodeZYX(@Apogy(units="m")double tx, @Apogy(units="m")double ty, @Apogy(units="rad") double tz, @Apogy(units="m") double rx, @Apogy(units="rad") double ry, @Apogy(units="rad") double rz) |
| |
| /** |
| * Creates a TransformNode using a pose expressed as a Matrix4d (4x4 matrix). |
| * @param matrix The matrix. |
| * @result The TransformNode created. |
| */ |
| op TransformNode createTransformNode(Matrix4d matrix) |
| |
| /** |
| * Creates a PickAndPlaceNode using a pose expressed as a Matrix4d (4x4 matrix). |
| * @param matrix The matrix. |
| * @result The PickAndPlaceNode created. |
| */ |
| op PickAndPlaceNode createPickAndPlaceNode(Matrix4d matrix) |
| |
| /** |
| * Creates an AttachedViewPoint. |
| * @param attachmentNode The node to attach the View Point in. |
| * @return The AttachedViewPoint. |
| */ |
| op AttachedViewPoint createAttachedViewPoint(Node attachmentNode) |
| |
| /** |
| * Return the 4x4 matrix expressing the pose of a specified Node in its root node. |
| * @param node The specified Node. |
| * @return The pose. |
| */ |
| op Matrix4d expressNodeInRootFrame(Node node) |
| |
| /** |
| * Return the 4x4 matrix expressing the pose of a Node's root in that Node reference. |
| * @param node The specified Node. |
| * @return The pose. |
| */ |
| op Matrix4d expressRootInNodeFrame(Node node) |
| |
| /** |
| * Computes the transformation to express the sourceFrame into the targetFrame. Both Nodes |
| * must share the same topology tree for the result to be valid. |
| * @param sourceFrame The frame to transform into the target frame. |
| * @param targetFrame The frame into which to express the source frame. |
| * @return The transform used to express the source frame in the target one. |
| */ |
| op Matrix4d expressInFrame(Node sourceFrame, Node targetFrame) |
| |
| /** |
| * Returns all Nodes for which the description matches a specified string. |
| * @param description The description to match. |
| * @param root The root node of the topology. |
| * @return The list of matching Nodes. |
| */ |
| op Node[] findNodesByDescription(String description, Node root) |
| |
| /** |
| * Returns all Nodes for which the Id matches a specified string. |
| * @param nodeId The Id to match. |
| * @param root The root node of the topology. |
| * @return The list of matching Nodes. |
| */ |
| op Node[] findNodesByID(String nodeId, Node root) |
| |
| /** |
| * Returns all Nodes that are matches or are sub-classes of a specified EClass. |
| * @param clazz The EClass to match. |
| * @param root The root node of the topology. |
| * @return The list of matching Nodes. |
| */ |
| op Node[] findNodesByType(EClass clazz, Node root) |
| |
| /** |
| * Returns the root node (i.e. moves up the topology tree until the ultimate parent node is found) of a specified Node. |
| * @param node The specified Node. |
| * @return The root Node. |
| */ |
| op Node findRoot(Node node) |
| |
| /** |
| * Returns whether or not two specified Nodes shared the same topology tree. |
| * @param node1 The first Node. |
| * @param node2 The second Node. |
| * return True if the nodes share the same root Node. |
| */ |
| op boolean doNodesShareTopologyTree(Node node1, Node node2) |
| |
| /** |
| * Finds the list of Nodes that connects fromNode to toNode. |
| * @param fromNode The node from which to start. |
| * @param toNode The destination node. |
| * @return The list of nodes connecting fromNode to toNode. Never null. |
| */ |
| op List<Node> findNodePath(Node fromNode, Node toNode) |
| |
| /** |
| * Creates a NodePath leading from the fromNode to the toNode. |
| * @param fromNode The node from which to start. |
| * @param toNode The destination node. Note that this node MUST be part of the root node descendant. |
| * @return The NodePath, null if toNode is not a descendant of from Node. |
| */ |
| op NodePath createNodePath(Node fromNode, Node toNode) |
| |
| /** |
| * Resolves the Node referred by a NodePath given the root node. |
| * @param root The root node to start resolving the node path from. |
| * @param nodePath The nodePath referring to a Node. |
| * @return The Node resolve from the NodePath, null is no match is found. |
| */ |
| op Node resolveNode(Node root, NodePath nodePath) |
| |
| /** |
| * Returns the Euclidian (i.e. straight line) distance between two Nodes. The nodes must be part of a common topology tree. |
| * @param fromNode The first Node. |
| * @param fromNode The second Node. |
| * return The distance between the specified Nodes, NaN if the specified node do no share the same topology tree. |
| */ |
| op double getEuclideanDistance(Node fromNode, Node toNode) |
| |
| /** |
| * Returns the geodesic (i.e. along the connecting edges) distance between two Nodes. The nodes must be part of a common topology tree. |
| * @param fromNode The first Node. |
| * @param fromNode The second Node. |
| * return The distance between the specified Nodes, NaN if the specified node do no share the same topology tree. |
| */ |
| op double getGeodesicDistance(Node fromNode, Node toNode) |
| |
| /** |
| * Prints the topology as text to the console. |
| * @param root The root node of the topology. |
| */ |
| op void printTopology(Node root) |
| |
| /** |
| * Applies a NodeFilter to a list of Nodes. |
| * @param filter The filter to apply. |
| * @param nodes The list of Nodes on which to apply the filter. |
| * @return The list of Node that passes through the filter. |
| */ |
| op Collection<Node> filter(NodeFilter filter, Collection<Node> nodes) |
| } |
| |
| /* |
| * Abstract base class of all Node filters. |
| */ |
| abstract class NodeFilter extends IFilter<Node> |
| { |
| } |
| |
| /** |
| * NodeFilter based on a chain of filters. |
| */ |
| class NodeFilterChain extends CompositeFilter<Node> |
| { |
| } |
| |
| /** |
| * Node filter that filters Node based on their class type. |
| */ |
| @Apogy(hasCustomClass="true") |
| class NodeTypeFilter extends NodeFilter |
| { |
| /** |
| * The class to match. |
| */ |
| EClass clazz |
| } |
| |
| /** |
| * Base class for NodeFilter that use a regular expression matching as the way to determine if a node passes the filter. |
| */ |
| @Apogy(hasCustomClass="true") |
| abstract class RegexNodeFilter extends NodeFilter |
| { |
| /** |
| * The string representing the regular expression that needs to be matched. |
| */ |
| String regex |
| } |
| |
| /** |
| * A Node filter that filters Node based on their nodeId. |
| */ |
| @Apogy(hasCustomClass="true") |
| class NodeIdFilter extends RegexNodeFilter |
| { |
| } |
| |
| /** |
| * A Node filter that filters Node based on their description field. |
| */ |
| @Apogy(hasCustomClass="true") |
| class NodeDescriptionFilter extends RegexNodeFilter |
| { |
| } |
| |
| /** |
| * A Node filter that filter a Node on whether it is under the parent specified parent node. |
| */ |
| @Apogy(hasCustomClass="true") |
| class NodeIsChildOfFilter extends NodeFilter |
| { |
| /* |
| * The parent node. |
| */ |
| refers Node parentNode |
| |
| /* |
| * Whether or not to include the parent Node itself passes the filter. |
| */ |
| boolean parentNodeIncluded = "true" |
| } |