Skip to content

Updated Changelog for 2025 R2 #171

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

Merged
merged 1 commit into from
Jun 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions 2025R2/Discovery_Extensibility_Dev_Guide_25-R2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
###############
# folder #
###############
/**/DROP/
/**/TEMP/
/**/packages/
/**/bin/
/**/obj/
_site
11 changes: 11 additions & 0 deletions 2025R2/Discovery_Extensibility_Dev_Guide_25-R2/.vale.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
StylesPath = styles

MinAlertLevel = suggestion

Packages = Google

Vocab = ansys

[*.md]
Ignore = articles/shared/c_legal_frontmatter.md
BasedOnStyles = Vale, Google
5 changes: 5 additions & 0 deletions 2025R2/Discovery_Extensibility_Dev_Guide_25-R2/api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
###############
# temp file #
###############
*.yml
.manifest
2 changes: 2 additions & 0 deletions 2025R2/Discovery_Extensibility_Dev_Guide_25-R2/api/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# PLACEHOLDER
TODO: Add .NET projects to the *src* folder and run `docfx` to generate **REAL** *API Documentation*.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Accuracy

This section covers the following topics:

- **[Linear and angular resolution](../../../../UDA/add_api/architecture/accuracy/linear_angular_res.md)**

- **[Comparing lengths and angles](../../../../UDA/add_api/architecture/accuracy/compare_angles_lengths.md)**

- **[Comparing XYZ objects](../../../../UDA/add_api/architecture/accuracy/compare_xyz.md)**

- **[Comparing UV objects](../../../../UDA/add_api/architecture/accuracy/compare_uv.md)**

- **[Comparing geometry](../../../../UDA/add_api/architecture/accuracy/compare_geo.md)**



Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Comparing lengths and angles

The Accuracy class provides methods for comparing lengths and angles.

The CompareLengths method takes two arguments, *lengthA* and *lengthB*, and returns an integer result:

- -1 *lengthA* is less than *lengthB*.
- 0 *lengthA* is equal to *lengthB* to within linear resolution.
- +1 *lengthA* is greater than *lengthB*.

This method provides general comparison of two lengths, but for common situations, such as comparing with zero, or testing whether two values are equal, simpler and more readable methods can be used:

```
public static void Example(double lengthA, double lengthB) {
// same as CompareLengths(lengthA, lengthB) == 0
bool equalLengths = Accuracy.EqualLengths(lengthA, lengthB);

// same as CompareLengths(lengthA, 0) == 0
bool lengthIsZero = Accuracy.LengthIsZero(lengthA);

// same as CompareLengths(lengthA, 0) > 0
bool lengthIsPositive = Accuracy.LengthIsPositive(lengthA);

// same as CompareLengths(lengthA, 0) < 0
bool lengthIsNegative = Accuracy.LengthIsNegative(lengthA);
}

```

Corresponding methods are provided for angles: CompareAngles, EqualAngles, AngleIsZero, AngleIsPositive, and AngleIsNegative.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Comparing geometry

To say that two surfaces or two curves are equal is ambiguous, since there is more than one interpretation of the concept. For example, with two planes:

- They could be coplanar, but the normals could be opposed.
- They could be coplanar, with normals having the same sense, but their frames and hence their parameterization might be different.
- They might be identical in every way.

You should not use the == operator with surface and curve types, since that will only test for reference equality.

`Geometry.IsCoincident` and `ITrimmedCurve.lsCoincident` are provided to make comparisons. They only test for coincidence, which means any of the above cases would pass.


Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Comparing UV objects

The same isn't true for the surface parameter UV types, PointUV, VectorUV, DirectionUV, and BoxUV, or for the curve parameter type, Interval. These types don't know whether the parameterization they represent is linear, angular, or some other type. For example, for a plane, the U parameterization is linear, but for a cylinder, the U parameterization is angular. For a NURBS surface, the U parameterization is neither linear nor angular.

Therefore, you shouldn't use the == operator for these types. When comparing parameters, you should use the appropriate length or angle comparison method for each of the U and V values. For NURBS parameterization, angular comparison could be used, but it's safest to evaluate points and compare these instead.


Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Comparing XYZ objects

The basic XYZ types, Point, Vector, Direction, Box, and Frame, have resolution tests build in, so you can compare objects using the == operator. For example, two points are equal if the distance between them is less than the linear resolution, and two directions are equal if the angle between them is less than then angular resolution.

```
public static void Example(Plane plane, Point point) {
// project point onto plane
SurfaceEvaluation eval = plane.ProjectPoint(point);
Point pointOnPlane = eval.Point;

// points are the same if less than linear resolution apart
bool planeContainsPoint = point == pointOnPlane;

// ContainsPoint is more efficient, but gives the same result
Debug.Assert(planeContainsPoint == plane.ContainsPoint(point));
}

```


Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Linear and angular resolution

Internally, geometric calculations are performed to machine double precision. When comparing the results of calculations, values should always be compared to within a specific resolution. These resolutions are provided by the Accuracy class:

- Two lengths are considered equal if their difference is less than LinearResolution.
- Two angles are considered equal if their difference is less than AngularResolution.

For example, when ContainsPoint is called to determine whether a point lies in a surface, internally the distance from the surface might be calculated, and the result is true if this distance is less than LinearResolution.


Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Application integration

This section covers the following topics:

- **[Persistent identifiers](../../../../UDA/add_api/architecture/application_integration/persist_ids.md)**

- **[Replacements](../../../../UDA/add_api/architecture/application_integration/replacements.md)**

- **[Update states](../../../../UDA/add_api/architecture/application_integration/update_states.md)**


Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Persistent identifiers

Doc objects have persistent identifiers, called *monikers*, which can be recorded and later *resolved* to return the doc object again. The Moniker property returns a moniker for the doc object, and the Resolve method returns the doc object again.

Internally, master doc objects have an identifier, which is globally unique. Occurrences are identified by the instance, which is a master, along with the original object, which might itself be an occurrence. A moniker is an object that encapsulates the identifiers of the one or more master objects involved in the identity of the subject.

To record a moniker, you can record its string representation using ToString. The length of this string depends on the number of master objects involved. The format of this string isn't documented, so you shouldn't attempt to construct or modify such a string.

To convert the string representation back into a moniker, you can use `FromString`.

```
public static void Example(IDesignFace desFace) {
Document doc = desFace.Document;

// all doc objects provide a moniker
Moniker<IDesignFace> desFaceMonikerA = desFace.Moniker;

// resolve the moniker in the document to obtain the original object
Debug.Assert(desFaceMonikerA.Resolve(doc) == desFace);

// the string representation can be recorded
string monikerText = desFaceMonikerA.ToString();

// the moniker can be reconstructed from the string
Moniker<IDesignFace> desFaceMonikerB = Moniker<IDesignFace>.FromString(monikerText);
Debug.Assert(desFaceMonikerB.Resolve(doc) == desFace);
}

```

To resolve a moniker, a document must be provided as the context. Discovery allows more than one version of the same scdoc file to be loaded at the same time, so the same moniker could potentially be resolved in more than one document.

Since the internal identifiers involved are globally unique, there is no danger of resolving the moniker in an unrelated document. If you attempt to do so, `null` will be returned to indicate that the object was not found.


Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Replacements

If the doc object has been deleted, Resolve returns null to indicate that the object was not found. Sometimes doc objects can get replaced during a command. For example, if a design face is split during a modeling operation, it will be replaced by two new design faces. Perhaps one of these new design faces gets split itself, or perhaps one of them gets deleted.

Behind the scenes, replacements are recorded, and when Resolve is called, if the object has been replaced, the moniker automatically returns one of the survivors, or null if there are no survivors.

- If it is important to know whether the object is a survivor, rather than the original object, you can compare its moniker with the moniker you already have, using the == operator. If the object is a survivor, it will have a different moniker.
- If it is important to obtain all survivors, ResolveSurvivors can be used instead. Note that this method only returns surviving replacements, so if the object hasn't been replaced at all, no survivors are returned.


Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Update states

A doc object master has an *update state*, which tells you if the object has changed.

Each time the doc object master is changed, its update state changes. Conversely, if the update state hasn't changed, then the object hasn't changed. When an object is changed due to an undo \(or redo\) operation, its update state is undone \(or redone\) too.

The update state is persistent, so you can store its string representation and use it in another Discovery session.

```
public static void Example(DesignFace desFace) {
// doc object masters provide an update state
UpdateState beforeStateA = desFace.UpdateState;

// the string representation can be recorded
string stateText = beforeStateA.ToString();

ModifyDesignBody();

// test whether the design face was changed
if (desFace.UpdateState != beforeStateA)
Debug.WriteLine("Design face was changed.");

// the update state can be reconstructed from the string
UpdateState beforeStateB = UpdateState.FromString(stateText);
Debug.Assert(beforeStateA == beforeStateB);
}

```

Update states aren't provided for occurrences, but you can store the update states of the instances involved in the occurrence chain, along with the update state of the master. PathToMaster returns these instances.

The update state only represents the state of the object itself, and not the state of other objects it contains or references. For example, the update state of a part isn't changed if a child design body is modified. Similarly, although the update state of a component will change if its placement is modified \(since this is a property of the component itself\), the update state won't change if its template part is modified.


Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Geometry architecture

This section discusses the geometry architecture and includes the following sections:

- **[Documents and doc objects](../../../UDA/add_api/architecture/doc_objects/document_doc_objects.md)**

- **[Application integration](../../../UDA/add_api/architecture/application_integration/app_integration.md)**

- **[Storing custom data](../../../UDA/add_api/architecture/storing_custom_data/storing_custom_data.md)**

- **[Identifiers during export](../../../UDA/add_api/architecture/id_objects/ID_during_export.md)**

- **[Geometry and topology](../../../UDA/add_api/architecture/geo_topology/geo_topology.md)**

- **[Accuracy](../../../UDA/add_api/architecture/accuracy/accuracy.md)**

- **[Units](../../../UDA/add_api/architecture/units/units.md)**


Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Documents and doc objects

A Document is the unit of loading and saving. Assuming it has been saved, a document corresponds to a Discovery scdoc file on disk.

A DocObject is an object that belongs to a document. Doc objects aren't the only objects that get saved when the document is saved, but they are the only objects that have a Document property. Examples of doc objects include: Part, Component, DesignBody, DesignFace, DatumPlane, and Note.

Doc objects provide:

- A parent-child tree containment hierarchy.
- Monikers for persistent identification.
- Update states to indicate that the doc object has changed.
- Custom attributes for storing third party data.

This section contains the following topics:

- **[Parent-child hierarchy](../../../../UDA/add_api/architecture/doc_objects/parent_child_hierarchy.md)**

- **[Parts and components](../../../../UDA/add_api/architecture/doc_objects/parts_components.md)**

- **[Occurrence chains](../../../../UDA/add_api/architecture/doc_objects/occurrence_chains.md)**

- **[General objects and masters](../../../../UDA/add_api/architecture/doc_objects/gen_objects_masters.md)**

- **[Originals and masters](../../../../UDA/add_api/architecture/doc_objects/originals_masters.md)**

- **[Transforming to master-space](../../../../UDA/add_api/architecture/doc_objects/transform_master_space.md)**

- **[Getting occurrences](../../../../UDA/add_api/architecture/doc_objects/getting_occurrences.md)**



Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# General objects and masters

In general, a doc object is either an occurrence, or a *master*. When dealing with *general* doc objects \(doc objects that might be occurrences or masters\), interfaces are used, for example, IPart, IComponent, and IDesignBody. These all derive from IDocObject.

There are some methods and properties that for theoretical or practical reasons aren't presented by occurrences, and are therefore only presented by masters. When dealing with masters, classes are used, for example, Part, Component, and DesignBody. These all derived from DocObject, which implements IDocObject.

Part implements IPart, Component implements IComponent, and so on, so a master supports everything that a general object supports, and often more besides.

Note that although Part is always a root object, IPart may or may not be a root object. If the IPart happens to be a master, then it's a root object, but if it happens to be an occurrence, its parent will be an IComponent or an IDrawingView.


Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Getting occurrences

Having done some work in master-space, it may be necessary to obtain an object in general-space. This is common if the original object came from the window selection, and you wish to set a new selection in the window.

The window selection is always in window-space, that is in the same coordinate-space as the scene shown in that window \(the same coordinate-system as `Window.Scene`\). So if the window shows an assembly, then the selected objects are in assembly space.

GetOccurrence can be used to obtain an object in general-space. It returns an occurrence that is similar to a companion object supplied. Note that the companion object is a general object, which may or may not be an occurrence. If it is an occurrence, then an equivalent occurrence is returned for the subject. If it isn't an occurrence, then the subject itself is returned. This allows you to write code that works correctly without testing whether the object is in fact an occurrence.

```
Public static void Example() {
Window window = Window.ActiveWindow;
if (window == null)
return;

// the selected component is in window-space
IComponent oldComp = window.SingleSelection as IComponent;
if (oldComp == null)
return;

// copy the component master
Component oldMaster = oldComp.Master;
Component newMaster = Component.Create(oldMaster.Parent, oldMaster.Template);
newMaster.Placement = oldMaster.Placement;

// get an occurrence of the new master in window-space
IComponent newComp = newMaster.GetOccurrence(oldComp);

// select the newly created component
window.SingleSelection = newComp;
}

```


Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Occurrence chains

If the template object itself contains instances, occurrences of occurrences are produced. For example, this happens with a two-level assembly, since the top-level assembly contains a component that instantiates a sub-assembly part, which itself contains a component that instantiates a piece part.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Originals and masters

IDocObject is the base for all doc object functionality. It provides members for traversing the parent-child hierarchy \(Children, GetChildren<T\>,GetDescendants<T\>,Parent,GetAncestor<T\>,Root\), which we have already met, and it also provides members for traversing the occurrence structure:

- Original: Gets the original IDocObject, else null if this is a master.
- Master: Gets the ultimate original, that is the DocObject master at the end of the occurrence chain. If the object is a master, the object itself is returned.
- Instance: Gets the instance that produces this occurrence, else null if this is a master.

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Parent-child hierarchy

Doc objects are part of a parent-child containment hierarchy, where the *parent* represents the container and the *children* represent the contents. If a doc object is deleted, all its *descendants* \(its children, recursively\) are also deleted.

For example, a Part contains zero or more DesignBody objects, each of which contains one or more DesignFace objects. The parent of a design face is a design body, and the parent of a design body is a part. Similarly, a design body is a child of a part, and a design face is a child of a design body.

```
Public static void Example(DesignBody desBody) {
Part part = desBody.Parent;

// a part is a root object, so it has no parent
Debug.Assert(part.Parent == null);
Debug.Assert(part.Root == part);

// GetChildren<T> returns immediate children of type T
foreach (DocObject child in part.GetChildren<DocObject>()) {
// Parent returns the immediate parent
Debug.Assert(child.Parent == part);
}

// DesignBody.Faces is equivalent to GetChildren<DesignFace>
foreach (DesignFace desFace in desBody.Faces) {
// Root returns the topmost parent
Debug.Assert(desFace.Root == part);
}

// GetDescendants<T> gets all nested children of type T
// the search starts with the object itself
foreach (DesignFace desFace in part.GetDescendants<DesignFace>()) {
// GetAncestor<T> crawls up the parent chain to find an object of type T
Debug.Assert(desFace.GetAncestor<Part>() == part);

// the search starts with the object itself
Debug.Assert(desFace.GetAncestor<DesignFace>() == desFace);
}
}

```

The parent chain continues up the hierarchy until the *root* object is reached. This is the topmost parent, which itself has no parent \(its parent is null\). Examples of root objects are: Part, DrawingSheet, and Layer.

All doc objects in the same parent-child hierarchy belong to the same document. The Document class provides properties to access its root objects: MainPart, Parts, DrawingSheets, and Layers.


Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Parts and components

A Part contains zero or more DesignBody objects and zero or more Component objects. This means a part can contain both design bodies and components, in which case it's neither a pure piece part, nor a pure assembly. This is supported so that the interactive user can restructure design bodies into components, or vice versa.

A component is an *instance* of a *template* part. It has a *placement* matrix to position the component into assembly space. The template is neither a child nor a parent of the component. If the parent-child hierarchy is visualized as an inverted tree structure with the root at the top and leaf nodes at the bottom, then the template is a sideways reference to another part, which is the root of another hierarchy.![](../../../../images/clip_image002_-854738110.png)

The template part may live in the same document as the component, giving rise to what the interactive user would call an *internal component*, or it may live in another document, giving rise to an *external component*. Strictly speaking, it's the template part that's either internal or external, not the component itself.

Loading