Geometry or computational domain for CFD simulation requires a water tight geometry with simplification to handle the mesh creation process. Solution of computational domain refers to 2D or 3D geometry in which fluid flow and/or heat transfer phenomena need to be solved. This is known as "ZONES" in FLUENT, "REGIONS" in STAR-CCM+ and "DOMAIN" in CFX. These are "volumes surrounded by closed surfaces(called boundaries)" in 3D and "areas closed by edges or lines (called boundaries)" in 2D. It is the mesh and nodes generated to define and represent the physical space mathematically. No geometrical information is associated with the solution domain.
The geometry creation for CFD can be accomplished by either of the following two methods:
Other operations include: extract centrelines (to plot variation of pressure or temperature vs. position), create mid-planes (to create plots on a non-planar surface), save curve data into .csv file, create enclosure, merges faces, create body-of-influence (BOI) geometry, create Face of Influence (FOI) geometry, scale-up or down a body... ANSYS Discovery has option to create Curve Tables and Hole Tables (Curve Table in the Annotation group under Detail tab), the centreline of a tube can be generated using 'Extract' tool in Beam section under Prepare tab. Fill Surface: create surfaces from free edges of a hole in a facet sheet body, Sew Sheet bodies: combine or sew multiple facet bodies into a single body, Bridge surface: (similar to loft operation in some CAD tools) create a body between two sets of edges of existing facet bodies. Extruding surfaces and sketches directly up to any user defined Plane with the "Up to Plane" method. Keep or delete imprinted edges when uniting bodies.
Creation of post-processing planes: when computational domain is not aligned to coordinate axes or the flow path are curved and twisted that any section would result in multiple non-contiguous surfaces, it is strongly recommended to create post-processing planes during geometry creation and meshing process. These faces should be named with prefix 'post_' and set as internal type in meshing (so that boundary layers do not grow over them). Though most of the solvers and post-processors has option to import such surfaces in STL format and imprint on the mesh, it is time consuming and may result in interpolation error. The 'internal' zone created shall have faces and nodes aligned on it and the solution variables are directly available there to calculate derived parameters such as mass flow rate and pressure. In case of imprinted surfaces, the solution variables have to be interpolated from nearest nodes, face and cell centers.
Unit Systems
Every designer needs to work on length units and thus all CAD modeling program or tool have some built-in features for default units and ways to convert from one units to others. The following image describes options to select unit system in SCDM.All tools dealign with virtual geometry and mesh generation has option to scale the model. As units are not mentioned at every numerical value, scaling changes the value as per units specified. For example, for a cylinder the tool may contain information 'mm' in header row and only numbers for diameter, length and other keypoints (nodes, vertices...). When user changes the units to 'm', those values has to be divided by 1000 while only the header gets changed from 'mm' to 'm'.
Parametric Modeling (Geometry Creation) within CFD Environment
For optimization studies, ANSYS Workbench offers options to make simulations in the order defined as DOE (Design of Experiment) table, each row termed as Design Point. ANSYS SpaceClaim and Discovery has option to parametrize the geometrical operations such as Pull, Move... which can be used to change the shape, size and location of bodies. Such activities are specially important in situations where periodicity and symmetry exist such as heat exchangers, fins, external aerodynamics.Parametric Modeling in ANSYS SpaceClaim / Discovery: For all operations which can be parametrized, the symbol 'P' in SpaceClaim and icon within context-menu in Discovery appear to create a parameter. The value field of a parameter can contain basic formula such as 0.02 * 25.4 to convert a dimension from inch to 'mm'.
The Groups tab contains Named Selections, Driving Dimensions and Script Parameters. Driving dimensions can be Measurement, Ruler Dimension, Pattern Count... When a Pull operation is initiated, the option to make it parametric appears only after a value is entered (after pressing the space bar). Similarly, Ruler Dimension can be used to change the size as shown below in one of videos from Ozen Engineering."Driving dimensions are created when there is a dimension on screen or a dimension in the properties panel." For example, selecting the round (fillet) and then clicking Create Group in the 'Groups' panel creates a "driving dimension" instead of a "named selection" because the face selected is a round, which has a dimension property that can be controlled from the property panel. Similarly, a "round group" is created each time fill operation is used to create a round (fillet) and is saved in the Filled Rounds folder.
Note: clicking on a driving dimension created with 'Pull' operation automatically activates the 'Pull' operation ↴
Note that the GUI in the two videos are a bit old and in recent versions, Create Group has been replaced with Create NS and Create Parameter. When a dimension is showing and "Create Parameter" is clicked, it usually create a driving dimension with initial value appearing on the screen. The orientation of Move handle can be changed by using the Direction tool guide, holding Alt and selecting a reference object, or by dragging a ball on the axes of the Move handle. That is, Alt + click a point or line orients one of the axes of Move handle towards that point or along that line. Alt+click on a plane, the direction of movement is set perpendicular to the plane. Steps to create Driving Dimensions using Move operation ↴The behaviour of the Move tool changes based on what is selected and direction of axes of move handle change based on the orientation on the screen. Press Ctrl to copy the object selected for movement and place it at the location at which user drags or dimensions the move. Video titled "Using Ansys SpaceClaim and Ansys Discovery for Parametric CAD Modeling" from KETIV Technologies gives good explanation of the methods described above. As per help.spaceclaim.com/2016.0.0/en/Content/Groups.htm: Group order is important because they are changed from top to bottom when the change is initiated in an external application.
Steps to create Move handle at 'Zero' initial value is explained below. The yellow centre sphere of Move handle turns into a blue cube when the Move handle is anchored.
Move operation is very much similar to Pull operation though the behaviour of the Move tool changes based on what is selected. Though Pull allows operation in only one direction, Move allows operation in multiple directions. If an entire object, such as a solid, surface, or sketch is selected, 'Move' operation translates or rotates the object. If one side of a solid, surface, or sketch is selected, move operation shall enlarge or reduce the size of the object. If an object is moved into another object in the same component, the smaller object is merged into the larger one and receives the larger object's properties. Moving the apex of a cone changes the height, Anchor the Move tool to the outer face to scale the cone.
By default the 'Move' handle seems to be placed at the centroid of chosen objects (faces, edges...). However, there are cases when an axis was create using same set of objects, the location of origin of the axis and location or the origin of move handle were not coincident. In absence of clear documentations, following error may occur.Create Driving Dimension using Measurements from within the Pull Tool: referenced from User Guide
From Workbench (V20) User Guide: "Negative dimension values can invert the direction vector of operations with which they are associated. This change is applied to the current and subsequent design point updates. As a result, when a Workbench input parameter is used as a driving dimension for a geometry, negative dimension values can result in unexpected geometric changes."
Geometry Fully or Partially Enclosed in a Fluid Domain
It is not explicitly documented in SCDM user manual in which order the parameters get updated - however it is logical to assume that the parameters shall get updated in the order they are created / stored. And the parameters are stored in the order they are created and not in the order sorted by user say ascending alphabetically. It is better to define parameters with constant reference frame instead of taking reference from any other floating object.
ANSYS WB as in version 2024 does not allow to change the ID of parameters though GUI and they are stored in the order they are created. Parameter ID can be changed by editing the Workbench project file *.wbpj using a text editor. Search for all instances of a parameter which usually is named as P** where ** represents the sequence number (such as P1, P2, P13, P21...) and replace them by the new name (preferably keeping the naming convention same). If parameters have been used in expressions, renaming parameters should take care of keeping this dependency.Few Recommendations for Parametric Modeling
In general (for a single solid body and not assembly), the order of update of parameters or driving dimension should not matter. If the order of update affects the final shape and size of the body, recheck the input dimension - they might not be correct. For example, some update might have resulted in loss of feature (a face or edge) leading to missing reference for next update.
When a parameter is changed in SCDM, the geometry change is updated but the parameter set value does not update in Workbench parameter set. User the option Update Parameter in SpaceClaim under the 'Workbench' tab which will push the updated value to Parameter set.Using an Excel Spreadsheet to Drive Dimensions
This utility is part of add-ins which can be activated using SpaceClaim Options > Add-ins > (Check the box) Excel Dimension Editor Add-in > Restart SpaceClaim.Driving Changes with Annotation Dimensions
3D annotation dimensions can be used to change design using the Pull and Move tools. Annotation dimensions can be used in combination with ruler dimensions. Dimension can be used for every element in design, from lines in sketches to faces of solids. In Discovery SpaceClaim, dimensions are not constraints rather tools for precise control during the creation or modification of a design. To save a dimension with the design, Ruler Dimension option can be used when pulling or moving.As per innovationspace.ansys.com/ ... /driving-parameter-and-script-parameter:
# Get list of named selections and driving dimensions in Groups tab dims_NS = Window.Groups.GetValue(Window.ActiveWindow) # # 3-tuple type: value is index 1, type is index 2 # Type = (Linear, Angular, Arc, Area, Diametric, Mass, Volume) dims_NS[0].TryGetDimensionValue() dims_NS[0].SetDimensionValue(value)A script to move objects defined by Named Selection is described below (not tested - generated by AI). Note that SCDM recording feature does not capture steps to create ruler dimensions. And hence the ruler dimensions cannot be accessed in Python script - changing ruler dimension is same as executing a move operation.
import SpaceClaim.Api.V242 as sc
from SpaceClaim.Api.V242 import Point, Direction, DesignPoint
#from SpaceClaim.Api.V242 import *
'''
User Inputs: Named Selections and Move Direction
object_to_move = Named selection for object(s) to move
move_dir_name = Named selection of face/edge to get direction
ref_point_name = Named selection of a vertex or point
move_distance = Distance to move in [mm]
'''
object_to_move = "ns_fillet_x"
move_dir_name = "ns_mmv_dir_1"
ref_point_name = "ns_ref_pnt_1"
ns_move_anchor = "ns_anchor"
move_distance = 50
target_selection = Selection.CreateByGroups(SelectionType.Primary, object_to_move)
move_direction = Selection.CreateByGroups(SelectionType.Primary, move_dir_name)
anchor = Selection.CreateByGroups(SelectionType.Primary, ns_move_anchor)
direction = Move.GetDirectionAlignedTo(target_selection, move_direction)
# or
direction = Move.GetDirectionAlignedTo(anchor, move_direction)
# or
direction = -Direction.DirZ
# or move by face normal
move_face = Selection.CreateByGroups(SelectionType.Primary, ns_move_face)
direction = Move.GetDirection(move_face)
#
options = MoveOptions()
'''
options.CreatePatterns = False
options.DetachFirst = False
options.MaintainOrientation = False
options.MaintainMirrorRelationships = True
options.MaintainConnectivity = True
options.MaintainOffsetRelationships = True
options.Copy = False
options.SnapAssociatedVertices = True
options.SubProportionalRadius = MM(0)
'''
result = Move.Translate(target_selection, direction, MM(5), options, Info1)
# Get direction vector from edge or planar face normal
direction_item = move_direction.Items[0]
if direction_item.ShapeType == sc.ShapeType.Edge:
curve = direction_item.Geometry
direction_vector = (curve.EndPoint - curve.StartPoint).Direction
elif direction_item.ShapeType == sc.ShapeType.Face:
face = direction_item.Geometry
direction_vector = face.Normal
else:
raise Exception("Move Direction must be an edge or planar face.")
reference_point = Selection.CreateByGrousp(ref_point_name)
if reference_point and reference_point.Count > 0:
ref_item = reference_point.Items[0]
if hasattr(ref_item, 'Point'):
ref_point = ref_item.Point
else:
ref_point = ref_item.Shape.Geometry.Center
else:
ref_point = Point.Origin # default to origin if not specified
move_vector = direction_vector * move_distance
transform = Transform.CreateTranslation(move_vector)
result = Move.Execute(target_selection, transform)
print(f"Moved '{object_to_move}' by {move_distance} along '{move_direction}'")
def get_named_selection(ns_name):
select_ns = Selection.CreateByGroups(ns_name)
if not select_ns or select_ns.Count == 0:
raise Exception(f"Named Selection '{ns_name}' not found or empty.")
return select_ns
# Create Driving Dimension as parameter and apply initial transform of 0 [unit]
axis_map = {
"X": coordinate_system.XDirection,
"Y": coordinate_system.YDirection,
"Z": coordinate_system.ZDirection
}
if move_axis not in axis_map:
raise Exception("Invalid move_axis. Choose from 'X', 'Y', or 'Z'.")
selected_axis = axis_map[move_axis]
end_point = ref_point + 1.0 * selected_axis
ruler = RulerDimension.Create(target_selection, ref_point, end_point)
ruler.Parameter.SetName(f"p11_{move_axis}_x1")
ruler.Parameter.IsIndependent = True
initial_transform = Transform.CreateTranslation(selected_axis * 0)
Move.Execute(target_selection, initial_transform)
Get summary of dimensions for edges and/or faces
ns_list = GetActiveWindow() .ActiveWindow .Groups mea_dim = [] for ns in ns_list: if (ns.GetNames().Contains("msr")): ns_members = ns.Members mea_dim.append(ns_members[0].Shape.Length) # Output is in [m] mea_dim_row = ','.join(mea_dim) print(mean_dim_row)From discuss.ansys.com under topic "Extract edge length and export information":
import os import io import json file_path = os.path.join(r"D:\Projects", "edge_lengths.json") bodies = GetRootPart().GetAllBodies() body = bodies[0] edge = body.Edges[0] e_length = edge.Shape.Length len_dict = { "edge length" : e_length } with io.open(file_path, "w", encoding="utf8") as json_file: json.dump(len_dict, json_file, ensure_ascii=False)
Material | Recommended maximum velocity |
Low Carbon Steel | 10 ft/sec - 3.0 [m/s] |
Stainless Steel | 15 ft/sec - 4.5 [m/s] |
Aluminum | 06 ft/sec - 1.8 [m/s] |
Copper | 08 ft/sec - 2.4 [m/s] |
90-10 Cupronickel | 10 ft/sec - 3.0 [m/s] |
70-30 Cupronickel | 15 ft/sec - 4.5 [m/s] |
A convenient frame of reference must be defined that applies to both model and prototype and corresponding locations must be defined using dimensionless ratios (for a sphere for example, angle on its surface, longitude and latitude lines). Thus, there exist similar conditions for corresponding points on both model and prototype. That is, the drag coefficient at a particular point on the sphere applies to both model and prototype.
The designer must follow, then geometric similarity (model and prototype), kinematic similarity (velocity vector direction is similar for both model and prototype), dynamic similarity (force vector direction is similar for both model and prototype), thermal similarity (heat fluxes)...
Note that similarity principles cannot be applied for all application without loss of accuracy. For example, to reduce size of an axial flow fan with shroud, either for numerical or experimental investigation, their is no thumb rule to account for blade-tip and shroud clearance. Hence, the designer has to establish his own "quality standards and acceptance criteria" to address this limitation
Domain size reduction by sub-modelling
Domain size reduction by axi-symmetry
The pre-processing activities require geometry simplifications (defeaturing) and ANSYS SpaceClaim has some powerful non-parametric features. One of them is the 'Pull' option (short-cut 'p') which is equivalent to 'sweep' or 'extrude' operation. By default, pull direction is tangent to the selected edge or perpendicular to the selected face. A direction can be chosen or pulled (sweep) along a curve. Selection: all holes equal to selected radius, all holes of same radius in same face, all holes of radius equal or smaller than select radius. Blend (b): create surface by two lines (it is equivalent to 'loft' operation in some CAD programs). Fill (f): create surface from a closed loop of curves. Move (m): the 'origin' option is to select the reference point on the source object.
Step-by-Step for Geometry Defeaturing and Simplifications (ANSYS Spaceclaim)
Step-1:
Split the large assemblies into smaller (if possible, geometrically less-dependent) domain. This helps avoid large memory requirement and further geometry clean-up operations as well.Step-2: Re-group and rename the data
The geometry in CAD environment is created keeping in mind the physical construction and assembly sequences. This is not important in mesh generation. It is better to re-group the geometrical (CAD) entities in terms of expected boundary definition. This makes it easy to operate on a smaller section of the entire domain. The selection, hide/unhide and operations such as imprint/ interference become faster.Step-3:
Further segregate the geometry into 'Solids' and 'Surfaces'. This helps chose operations appropriate for the respective category. Such as fillet removal, split, booleans and extrude (pull) is easy on solids.Step-4:
Convert the solids with thin wall thickness into solids with no internal wall and void. For example, a beam with fillets and internal wall.
Step-5:
Before removing the wall thickness, use the operations appropriate for solids such as Booleans like unite, intersect... to make sure the once converted to surface, no further operations such as extend /intersection is needed to remove the gaps / connect the surfaces. Note that this method is no recommended for FEA simulation. in CFD the blockage of flow is important where as in FEA the location of centroid is important.
Step-5:
ANSYS Spaceclaim is a CAD-type pre-processor and works better on solids. CFD volume extraction is a analogous to 'negative' of visible solid volumes. Instead of deleted the unwanted surfaces one-by-one, it is recommended and worth trying to create a "bounding box" enclosing the geometry and use a booleaan to subtract the solids from the 'bounding' box. The resultant negative volume of fluid domain is easy to operate and remove the protrusions generated due to gaps in original (input) geometry.SpaceClaim has versatile feature called Pull operation which can be used to extrude faces and edges, create fillets and chamfer and remove materials. Tangent and Natural (curvature continuous) extension can be toggled when dragging the end of a curve. To drag the extension Tangent to the curve, press and hold Ctrl prior to dragging. Press 'Ctrl' and drag to 'Pull' the curve end tangent to the curve. Surface edges can be Pulled normal to their neighbouring face. Press the Ctrl key when you begin the Pull. Press Ctrl and drag to Pull the edge tangent to the surface. Pulling a face with its edges selected extrudes the face without influence from neighbouring faces. Pulling a conical face "Up To" a parallel cylindrical face replaces the cone with the cylinder if the axes are close together. Otherwise, the conical face is replaced with a cylindrical face that is coaxial to the cone and has the same radius as the cylinder.
Definition: gaps in the plane of a surface is called lateral (horizontal) gaps and gaps in the direction of area normal is called the transverse (vertical) gap.
If you are dealing with large surfaces with small (transverse) gaps (say < 1% of the biggest geometry or say 1-5 [mm] which you can neglect), follow these steps:
Fill operation: selecting many contiguous (connected) surfaces for fill operation does not work. However, selecting just one surface out of many makes the 'fill' tool act nicely. If 'fill' operation does not work while removing fillets and rounds, use Delete Rounds under Prepare > Remove > Rounds. Many a times, the sequence of fill operation determines the success of operation especially when fillets of different radii are connected in a loop. One need to visualize that the deletion of a fillet or blend should result in valid geometry.
Do not 'stitch' the geometry body and surfaces until you are done with all necessary clean-up and simplifications.
'Imprint' and 'Interference' operations do not make intended change in on go. Continue the operation till you get a message "No problem areas were fixed".
In ANSYS SpaceClaim, sometimes 'pull to' operation does not work. However, you can manually 'pull' or 'extend' the edges to or beyond the desired target edge. Hence, extend the edges manually and split them later to have a common boundary. Another option is to copy the surface(s) into a new model file and then do pull / fill / trim operations. Once desired shape is achieved, copy-paste the new geometry or shape back into main assembly.
Sometimes, the edges of the surfaces forming the gaps are short and split into many segments. Most of the geometry defeaturing programs have option to Fit Curves. However, this operation may not work if curves are already associated with surface. In ANSYS SpaceClaim, Patch Fill is another option. First click on Fill Ribbon tool without selecting any geometry. Under the options, the default is Extend Fill. Change the option to Patch Fill. If any geometry was previously selected, it would have extended fill.
ANSYS Discovery has option to save all the components into separate files. Select the components, right-click and chose Convert to External. The icon for the component in the Structure tree changes to indicate 'external'. A batch converter converter.exe located in the install directory of Discovery can be used to convert files to other formats.
If the bodies are stored without components, directly under root components, select the bodies which needs to be saved in separate files, right click and chose "Move Each to A Component". This will move each body in separate components and the steps mentioned earlier can now be used to save them into separate files. Discovery has different type of components: internal, external, dependent and independent.
How to compare two geometry when external appearance look similar? One way is to check the surface area - the one with higher value is expected to have bigger cross-section and lengths. This can be further confirmed by comparing the volumes of the two geometries.
Other products offering similar features are Maya 3D and Houdini. From the website of Autodesk: "What is Maya? Maya is professional 3D software for creating realistic characters and blockbuster-worthy effects. Bring believable characters to life with engaging animation tools. Shape 3D objects and scenes with intuitive modelling tools. Create realistic effects – from explosions to cloth simulation." From the official page of Houdini: "Houdini is built from the ground up to be a procedural system that empowers artists to work freely, create multiple iterations and rapidly share workflows with colleagues. In Houdini, every action is stored in a node. These nodes are then “wired” into networks which define a “recipe” that can be tweaked to refine the outcome then repeated to create similar yet unique results. The ability for nodes to be saved and to pass information, in the form of attributes, down the chain is what gives Houdini its procedural nature."
Like many feature rich applications, the interface of Blender is a bit intimidating (complex and lost in ocean type) when you open it the first time. Understaing the GUI layout and context based sub-menu is key to get started.
Some challenges dealign with tessellated geometries are removing fillets and chamfers from imported say STL file, deleting coincident surfaces (common boundaries of two closed volumes), removing proximities at sharp corners and point contacts such as a tire contacting flat ground.
ANSYS Discovery (known as SpaceClaim and DesignSpark) has on option called Vectorize Image that creates curves around colored areas in images. This can be used to create a 2D domain from images. A colour convention can be use to define domain and material types (solid, fluid, insulator...).
Linear parametric equation of curves: x = a + b.u, y = m + n.u, z = p + q.u where a, b, m, n, p and q are constants. The curves starts at p(u=0) = [a m p] and ends as [(a + b) (m + n) (p + q)] with direction cosines proportional to b, n and q.
Cubical parabola: x = a.u, y = b.u2, z = c.u3 where a, b and c are constants.
Left-handed circular helix: Also known as machine screw, the curves are described as x = r.cos(u), y = r.sin(u), z = p.u where r and p are constants. It is the locus (path) of a point that revolves around the z-axis at radius r and moves parallel to the z-axis at a rate proportional to the angle of revolution 'u' (known as pitch of the helix). Note that if p < 0 then it is a right-handed screw (helix).
All the 3 examples above demonstrate the versatility of parametric representation of a curve. However, we need to always have a independent variable (u or θ) as parameter. Even, x or y or z themselves can be a parameter so that x=f(x), y=g(x) and z=h(x). Similarly, the surfaces can be represented parametrically. This is the reason the 3D CAD geometry in SolidWorks, Unigraphics, Creo, Inventor, FreeCAD... are called parametric models and the method is called parametric modelling.Algebraic Form of a Parametric Cubic (PC) Curve: Following 3 polynomials are required to define any curve segment of a PC curve:
x(u) = a0 + a1u + a2u2 + a3u3
y(u) = b0 + b1u + b2u2 + b3u3
z(u) = c0 + c1u + c2u2 + c3u3
The unique set of 12 constant coefficients are known as algebraic coefficients and determines the size, shape and position of the curve in space.Geometric Form of a Parametric Cubic (PC) Curve: Algebraic coefficients do not lend much flexibility to control the shape of a curve in modelling situations as they do not account for conditions as its ends points or boundaries. When a curve is described based on its conditions as the ends (such as end point coordinates, tangents, curvature, torsion...), it is called geometric form of the curve.
Create Periodic Planes
The easiest option is to cut the geometry with two planes inclined at desired sector angle and passing through the axis of rotation. This option any cut through the blades (rotating as well as stationary) through the domain shall still remain periodic by definition.
Another approach is to draw a plane passing between two adjacent blades, the plane need not pass through exactly middle point of the leading edges. Create another plane inclined to the first plane at required sector angle. Split the geometry by these planes.
The following method is similar to previous one except 5 to 8 planes may be required to split the geometry into axial and tangential directions.
CAD Data Exchange
STEP format is widely used in data exchange between CAD and numerical (FEA / CFD) simulations. It has many flavours known as AP: Application Protocol. Meta data such as surface names are included when using the STEP AP214. Most of the CAD programs including Siemens NX do not include surface names in a STEP (AP 242) export by default but they do have option to make the surface names included while using AP 214 of STEP format.Similarly, to define 'names' in PTC Creo, the design can use: File > Prepare > Open Model Properties, then select 'Names' in the model properties dialogue. Then select faces by clicking > enter a name in the dialogue box opened in previous step. During CAD export to STEP format with default settings, the 'names' defined earlier do not get stored in the file. Change the export setup through File > Options > Configuration Editor > intf_out_assign_names > set it to 'user_name'.
Sample Scripts from Public Domains
ClearAll() # Open Project File.Open(r"E:\Sctipts\Bracket.dsco") # convert CAD files and save them in the same directory import glob, os os.chdir(r"E:\Scripts\") for file in glob.glob("*.stp"): File.ResetProject() File.Open(os.path.join(os.getcwd(), file), ImportOptions.Create()) File.SaveAs(os.path.join(os.getcwd(), file[:-4]+".igs")) #run Discovery script in batch mode "C:\Program Files\Ansys Inc\v221\Discovery\Discovery.exe" --run-script \ "E:\Scripts\pipe.scscript" --hidden --exit-after-script # run Discovery script from WB project page import os myScriptGeometry = "E:\Scripts\pipe.scscript" #SetScriptVersion(Version="22.1.217") template1 = GetTemplate(TemplateName="Geometry") system1 = template1.CreateSystem() geometry1 = system1.GetContainer(ComponentName="Geometry") geometry1.Edit(IsDiscoveryGeometry=True) geometry1.RunScript(ScriptFile=myScriptGeometry,GeometryContainer="Geometry",useAsMacro="false") geometry1.Exit() def createPlaneOriginNormal(origin = [0, 0, 0], normalDirection = [0, 0, 1]): originPoint = Point.Create(origin[0], origin[1], origin[2]) dirZ = Direction.Create(normalDirection[0], normalDirection[1], normalDirection[2]) frame = Frame.Create(originPoint, dirZ) plane = Plane.Create(frame) return plane def getGroup(groupName): groups = GetActiveWindow().ActiveWindow.Groups for group in groups: if group.GetName() == groupName: return group return None def getDimensionValue(group): tryGetDimensionResult = group.TryGetDimensionValue() if tryGetDimensionResult[0]: return True, tryGetDimensionResult[1] else: return False, 0 def setDimensionValue(group, value): group.SetDimensionValue(value) # Fill selection = Face1 secondarySelection = Selection.Empty() options = FillOptions() result = Fill.Execute(selection, secondarySelection, options, FillMode.ThreeD, Info1) # Thicken Faces selection = FaceSelection.Create(Face0, Face1, Face2, Face3) options = ThickenFaceOptions() result = ThickenFaces.Execute(selection, Direction.Create(0.707, 0, 0.707), MM(-5), options) # Create Rounds selection = PowerSelection.Edges.ByLength(Edge1, PowerSelectOptions(True), SearchCriteria.SizeComparison.Equal) options = ConstantRoundOptions() result = ConstantRound.Execute(selection, MM(2.5), options, Info1) # Save Project As File.SaveAs(r"E:\Scripts\U-Bracket.dsco") # Create a block startPoint = Point.Create(MM(5), MM(5), MM(15)) endPoint = Point.Create(MM(20), MM(20), MM(20)) BlockBody.Create(startPoint, endPoint) # Create rectangles RectangularSurface.Create(MM(40), MM(5),Point.Origin) RectangularSurface.Create(MM(5), MM(40),Point.Origin) # Merge rectangles allSurfaceBodies = PowerSelection.Bodies.AllSurfaceBodies() result = Combine.Merge(allSurfaceBodies) # Create a plane and switch to sketch mode origin = [MM(5), MM(5), MM(5)] plane = create_a_plane_from_origin_and_normal(origin) ViewHelper.SetSketchPlane(plane) # Sketch Spline points = List[Point2D]() points.Add(Point2D.Create(MM(0), MM(15))) points.Add(Point2D.Create(MM(5), MM(5))) points.Add(Point2D.Create(MM(15), MM(0))) result = SketchNurbs.CreateFrom2DPoints(False, points) splineCurve = result.CreatedCurves[0] # Switch to 3D mode mode = InteractionMode.Solid ViewHelper.SetViewMode(mode) # Extrude spline selection = Selection.Create(splineCurve) options = ExtrudeEdgeOptions() result = ExtrudeEdges.Execute(selection, Point.Origin, Direction.DirZ, MM(30), options) resultFace = result.CreatedFaces ## Slice block by resultFace toolFaces = Selection.Create(resultFace) selection = PowerSelection.Bodies.AllSolidBodies() result = SplitBody.ByCutter(selection, toolFaces, True) # delete unncessary bodies referencePoint = Point.Create(MM(5), MM(5), MM(15)) for body in GetRootPart().GetAllBodies(): if not body.Shape.ContainsPoint(referencePoint): body.Delete() # Extrude resulting surface body faceToExtrude = result.GetModified[IDesignFace]() faceToExtrudeSelection = Selection.Create(faceToExtrude) options = ExtrudeFaceOptions() options.ExtrudeType = ExtrudeType.Add result = ExtrudeFaces.Execute(faceToExtrudeSelection, MM(40), options) # Create the named selections Selection.Create(GetRootPart().Bodies).CreateAGroup("SolidBody") for face in GetRootPart().Bodies[0].Faces: if (face.Shape.ContainsPoint(Point.Create(MM(2.5), 0, MM(2.5)))): Selection.Create(face).CreateAGroup("Fixed support") if (face.Shape.ContainsPoint(Point.Create(0, MM(2.5), MM(2.5)))): Selection.Create(face).CreateAGroup("Pressure load") #How to Access Groups groups = GetActiveWindow().ActiveWindow.Groups for group in groups: print group.GetName() #How to get all items of a Group/Named Selection group = GetActiveWindow().ActiveWindow.Groups[0] Group.Members #or Selection.CreateByGroups("Height").Items heightGroup = getGroup("Height") tryGetDimensionResult = heightGroup.TryGetDimensionValue() print tryGetDimensionResult topGroup = getGroup("Top") tryGetDimensionResult = topGroup.TryGetDimensionValue() print tryGetDimensionResult heightGroup = getGroup("Height") success, height = getDimensionValue(heightGroup) if success: print height heightGroup.SetDimensionValue(MM(5)) if success: print height setDimensionValue(heightGroup, height + MM(4)) #Using script parameter to create a surface Test = Parameters.Test print Test RectangularSurface.Create(Test,Test,Point.Origin) #Units of Script Parameters Length = Parameters.Length myUnits = UnitsHelper.GetDocumentUnits() print ("Parameter - SI units: " + str(Parameters.Length)) print ("Parameter - local units (" + myUnits.LengthProperties.Type.ToString() \ + "): " + str(Parameters.Length*myUnits.LengthFactor)) #Set radius2 to initial value minus radius1 divided by 3 r1Group = getGroup("radius1") success, radius1 = getDimensionValue(r1Group) r2Group = getGroup("radius2") success, radius2 = getDimensionValue(r2Group) if success: print radius2 setDimensionValue(r2Group, radius2 - radius1/3) Objects, Selections and Named Selections #Access Bodies: select bodies using part.Bodies Selection.Clear() part = GetRootPart() bodies = part.Bodies selection = Selection.Create(bodies) selection.SetActive() #Access Bodies: select bodies using part.GetBodies() part = GetRootPart() bodies = part.GetBodies() selection = Selection.Create(bodies) #select bodies using part.GetBodies(“filter”) part = GetRootPart() bodies = part.GetBodies("_2") selection = Selection.Create(bodies) #listing bodies using part.GetAllBodies() part = GetRootPart() bodies = part.GetAllBodies() for body in bodies: print body.GetName() #Index of bodies part = GetRootPart() bodies = part.GetAllBodies() for index,body in enumerate(bodies): print index,body.GetName() # Access Components: part = GetRootPart() for component in part.Components: print component.GetName() part = GetRootPart() for component in part.GetAllComponents(): print component.GetName() # Access Coordinate System: part = GetRootPart() for coordinateSystem in part.CoordinateSystems: print coordinateSystem.GetName() for coordinateSystem in part.Components[0].GetCoordinateSystems(): print coordinateSystem.GetName() for coordinateSystem in part.Components[0].GetAllCoordinateSystems(): print coordinateSystem.GetName() for coordinateSystem in part.GetDescendants[ICoordinateSystem](): print coordinateSystem.GetName() # Access Datum Plane part.DatumPlanes part.Components[0].GetDatumPlanes() part.Components[0].GetAllDatumPlanes() # Access Datum Lines part.DatumLines part.Components[0].GetDatumLines() part.Components[0].GetAllDatumLines() # Access Datum Points part.DatumPoints part.Components[0].GetDatumPoints() part.Components[0].GetAllDatumPoints() # Getting Faces of body: myBody = GetRootPart().Bodies[0] for myFace in myBody.Faces: myGeometry = myFace.Shape.Geometry if isinstance(myGeometry, Cone): ColorHelper.SetColor(Selection.Create(myFace), ColorHelper.Azure) if isinstance(myGeometry, Plane): ColorHelper.SetColor(Selection.Create(myFace), ColorHelper.Olive) if isinstance(myGeometry, Cylinder): ColorHelper.SetColor(Selection.Create(myFace), ColorHelper.Violet) # Getting Descendants myBody = GetRootPart().Bodies[0] myEgdes = myBody.GetDescendants[IDesignEdge]() mySel = Selection.Create(myEgdes) mySel.SetActive() # Getting newly created entities: myBody = GetRootPart().Bodies[0] myEgdes = myBody.GetDescendants[IDesignEdge]() mySel = Selection.Create(myEgdes) myOptions = ConstantRoundOptions() result = ConstantRound.Execute(mySel, MM(1), myOptions) mySelection = Selection.Create(result.CreatedFaces) ColorHelper.SetColor(mySelection, ColorHelper.Cyan) cfaces = result.CreatedFaces length_cfaces = len(cfaces) MessageBox.Show("Number of Created Faces:" + str(length_cfaces)) # Getting Modified entities myBody = GetRootPart().Bodies[0] myEgdes = myBody.GetDescendants[IDesignEdge]() mySel = Selection.Create(myEgdes) myOptions = ConstantRoundOptions() result = ConstantRound.Execute(mySel, MM(1), myOptions) mySelection = Selection.Create(result.CreatedFaces) ColorHelper.SetColor(mySelection, ColorHelper.Cyan) mySelection = Selection.Create(result.GetModified[IDesignFace]()) ColorHelper.SetColor(mySelection, ColorHelper.Magenta) # Operating on Object lists myBodies = GetRootPart().GetAllBodies() Selection.Create(myBodies).SetActive() myBodies.Remove(GetRootPart().GetAllBodies()[1]) Selection.Create(myBodies).SetActive() myBodies.Remove(GetRootPart().GetAllBodies()[2]) Selection.Create(myBodies).SetActive() myBodies.Add(GetRootPart().GetAllBodies()[1]) Selection.Create(myBodies).SetActive() # ---------------------Selecting entities-------------------------------------- mySel_0 = Selection.GetActive() for body in mySel_0.GetItems[IDesignBody](): print body.GetName() mySel_1 = Selection.CreateByNames("Cylinder") mySel_1.SetActive() Selection.Clear() mySel_1.GetInverse().SetActive() mySel_2 = Selection.CreateByGroups("Top") mySel_2.SetActive() mySel_3 = Selection.CreateByNames("Box") mySel_3.AddToActive() mySel_4 = Selection.SelectAll() mySel_4.SetActive() mySel_5 = mySel_4 - mySel_3 mySel_5.SetActive() # gets the current selection from the active view mySel_1 = Selection.GetActive() # creates inverted selection mySel_2 = mySel_1.GetInverse() # selects objects from this selection in active view mySel_2.SetActive() # Power Selection seedSelection = Selection.CreateByNames("b07") powSelection = PowerSelection.Bodies.ByVolume(seedSelection, PowerSelectOptions(True), SearchCriteria.SizeComparison.SmallerOrEqual) powSelection.SetActive() seedSelection = Selection.CreateByNames("b08") powSelection = PowerSelection.Bodies.ByVolume(seedSelection, PowerSelectOptions(False), SearchCriteria.SizeComparison.SmallerOrEqual) powSelection.SetActive() # Power Selection – selecting other bodies otherBodies=Selection.Create(GetRootPart().GetAllBodies()) options=PowerSelectOptions(False, otherBodies) seed=Selection.Create(GetRootPart().GetAllBodies("b03")) pSel=PowerSelection.Bodies.ByVolume(seed, options, \ SearchCriteria.SizeComparison.LargerOrEqual) pSel.SetActive() otherBodies=Selection.Create(GetRootPart().GetBodies()) options=PowerSelectOptions(False, otherBodies) seed=Selection.Create(GetRootPart().GetAllBodies("b04")) pSel=PowerSelection.Bodies.ByVolume(seed, options, \ SearchCriteria.SizeComparison.LargerOrEqual) pSel.SetActive() # Power Selection – selecting seed options=PowerSelectOptions(True,None,True) seed=Selection.Create(GetRootPart().GetAllBodies("b07")) pSel=PowerSelection.Bodies.ByVolume(seed, options, \ SearchCriteria.SizeComparison.SmallerOrEqual) pSel.SetActive() options=PowerSelectOptions(True,None,False) seed=Selection.Create(GetRootPart().GetAllBodies("b07")) pSel=PowerSelection.Bodies.ByVolume(seed, options, \ SearchCriteria.SizeComparison.SmallerOrEqual) pSel.SetActive() # Multiple Objects Selection b1 = GetRootPart().Bodies[0] b2 = GetRootPart().Bodies[1] b3 = GetRootPart().Bodies[2] # Approach 1 s1 = Selection.Create(b1, b2, b3) # Approach 2 body_list = [b1, b2] body_list.Add(b3) s2 = Selection.Create(body_list) # Approach 3 list = List[IDesignBody]() list.Add(b1) list.Add(b2) list.Add(b3) s3 = Selection.Create(list) # Approach 4 s4 = Selection.Create(b1, b2) s4 = s4 + Selection.Create(b3) s4.SetActive() # Mixed Selections b1 = GetRootPart().Bodies[0] b2 = GetRootPart().Bodies[1] b3 = GetRootPart().Bodies[2] f1 = b3.Faces[0] f2 = b3.Faces[1] # Approach 1 s1 = Selection.Create(b1, b2, f1, f2) # Approach 2 b_list = [b1, b2] f_list = [f1, f2] s2 = Selection.Create(b_list + f_list) s2.SetActive() # Multiple objects selection b1 = GetRootPart().Bodies[0] b2 = GetRootPart().Bodies[1] b3 = GetRootPart().Bodies[2] f1 = b3.Faces[0] f2 = b3.Faces[1] b_list = [b1, b2] f_list = [f1, f2] sel1 = Selection.CreateByObjects([b1, f_list]) sel2 = Selection.CreateByObjects([b_list, f_list]) sel3 = Selection.Create(b1, f1, f2) sel3.SetActive() #Creating Named Selections for face in GetRootPart().Bodies[0].Faces: myNS=NamedSelection.Create(Selection.Create(face),Selection()) if isinstance(face.Shape.Geometry, Cylinder): myNS.CreatedNamedSelection.SetName("sideWall") elif face not in Selection.CreateByGroups("inlet").GetItems[IDesignFace](): myNS.CreatedNamedSelection.SetName("outlet") else: myNS.CreatedNamedSelection.Delete() myNS=NamedSelection.Create(Selection.CreateByNames("cylinder"),Selection()) myNSName=myNS.CreatedNamedSelection.GetName() NamedSelection.Rename(myNSName,"myCylinder") Selection.Create(GetRootPart().Bodies[0]).CreateAGroup("myCyl") part = GetRootPart() for component in part.Components: bodies = component.GetAllBodies() selection = Selection.Create(bodies) selection.SetActive() # Move bodies to root component result = ComponentHelper.MoveBodiesToComponent(selection, part, False) # Delete Empty Components ComponentHelper.DeleteEmptyComponents(part) Selection.Clear() myBodies = List[IDesignBody]() part = GetRootPart() for body in part.GetAllBodies(): if body.Shape.Volume <= 3e-07 : myBodies.Add(body) Selection.Create(myBodies).SetActive() myFilter=3e-7 for body in GetRootPart().GetAllBodies(): if body not in GetRootPart().GetBodies(): ComponentHelper.MoveBodiesToComponent(Selection.Create(body),\ GetRootPart().Root) for comp in GetRootPart().GetAllComponents(): ComponentHelper.DeleteEmptyComponents(Selection.Create(comp)) myPowSel=PowerSelection.Bodies.ByVolume(myFilter, None, \ SearchCriteria.SizeComparison.SmallerOrEqual) myPowSelInv=Selection.Create(GetRootPart().GetAllBodies())-myPowSel result = ComponentHelper.MoveBodiesToComponent(myPowSel) result.CreatedComponents[0].SetName("smallBodies") result = ComponentHelper.MoveBodiesToComponent(myPowSelInv) result.CreatedComponents[0].SetName("bigBodies") #Demo 1: Creating cylinders by extruding surfaces ClearAll() Diameter = [10, 30, 20, 40, 60] Length = [50, 75, 25, 10, 60] z_offset = 100 # cylinder creation version 1 for i in range(len(Diameter)): myFace = CircularSurface.Create(Diameter[i]/2, Direction.DirZ, Point.Create(0, 0, sum(Length[:i])-Length[0] + z_offset)).CreatedBody.Faces options = ExtrudeFaceOptions() options.ExtrudeType = ExtrudeType.ForceIndependent result = ExtrudeFaces.Execute(Selection.Create(myFace), Length[i], options) result.CreatedBodies[0].SetName("Cylinder_v1_"+str(i)) Selection.Clear() ViewHelper.ZoomToEntity() # Solidify Sketch mode = InteractionMode.Solid result = ViewHelper.SetViewMode(mode) # Demo 2 # cylinder creation version 2 for i in range(len(Diameter)): CenterBottom=Point.Create(0, (sum(Length[:i]) - Length[0]) + z_offset, 0) CenterTop=Point.Create(CenterBottom.X, CenterBottom.Y + Length[i], CenterBottom.Z) DragPoint=Point.Create(Diameter[i]/2., CenterTop.Y, CenterTop.Z) result=CylinderBody.Create(CenterBottom, CenterTop, DragPoint, ExtrudeType.ForceIndependent) result.CreatedBodies[0].SetName("Cylinder_v2_"+str(i)) Selection.Clear() ViewHelper.ZoomToEntity() # Solidify Sketch mode = InteractionMode.Solid result = ViewHelper.SetViewMode(mode) #Demo 3 ClearAll() from math import tan, pi ConeHeight=0.02 ConeAngle=DEG(30) ViewHelper.SetSketchPlane(Plane.PlaneXY) pt1 = Point2D.Create(0, 0) pt2 = Point2D.Create(0, ConeHeight) pt3 = Point2D.Create(ConeHeight*tan(ConeAngle/2), 0) SketchLine.Create(pt1, pt2) SketchLine.Create(pt2, pt3) SketchLine.Create(pt3, pt1) result=ViewHelper.SetViewMode(InteractionMode.Solid) mySel=Selection.Create(result.CreatedBodies[0].Faces) myAxis = Line.Create(Point.Origin,Direction.DirY) myOptions = RevolveFaceOptions() myOptions.ExtrudeType = ExtrudeType.Add RevolveFaces.Execute(mySel, myAxis, DEG(360), myOptions) Selection.Clear() ViewHelper.ZoomToEntity() # Demo 4 ClearAll() pt1=Point.Origin pt2=Point.Create(MM(10), MM(2), MM(2)) result=BlockBody.Create(pt1, pt2, ExtrudeType.Add) b0=result.CreatedBody for i in range(10): mySel = Selection.Create(b0) direction = Direction.DirY options = MoveOptions() options.Copy = True result = Move.Translate(mySel, direction, (i+1)*MM(10), options) Selection.Clear() ViewHelper.ZoomToEntity() # Demo 5 ClearAll() pt1=Point.Create(MM(-10),MM(0),MM(0)) pt2=Point.Create(pt1.X+MM(2), pt1.Y+MM(2), pt1.Z+MM(2)) result=BlockBody.Create(pt1, pt2, ExtrudeType.Add) b0=result.CreatedBody for i in range(11): mySel = Selection.Create(b0) axis = Line.Create(Point.Origin, Direction.DirZ) options = MoveOptions() options.Copy = True result = Move.Rotate(mySel, axis, (i+1)*DEG(30), options) Selection.Clear() ViewHelper.ZoomToEntity() # Demo from SpaceClaim.Api.V21 import Command import os ClearAll() #Import the geometry my_path = os.path.dirname(GetActiveWindow().Document.Path) DocumentInsert.Execute(os.path.join(my_path, "valve1.dsco")) Selection.Create(GetRootPart().Components[0]).SetActive() c = Command.GetCommand("ImportComponentGroups") c.Execute() ViewHelper.ZoomToEntity() #Fill the surface holes < criteria criteria_radius = MM(7) total_selection = Selection.Empty() selection1 = PowerSelection.Faces.BySurfaceHoleRadius(criteria_radius, PowerSelectOptions(True), SearchCriteria.SizeComparison.SmallerOrEqual) total_selection += selection1 total_selection.SetActive() result = Fill.Execute(total_selection) #Remove all chamfers and rounds criteria_radius = MM(20) total_selection = PowerSelection.Faces.ByRoundRadius(criteria_radius, PowerSelectOptions(True), SearchCriteria.SizeComparison.SmallerOrEqual, SearchCriteria.RoundType.All) for body in GetRootPart().GetAllBodies(): for face in body.Faces: if isinstance(face.Shape.Geometry, Cone): total_selection += Selection.Create(face) total_selection.SetActive() result = Fill.Execute(total_selection) #Create missing bodies from Named Selections and move them to new components ComponentHelper.SetActive(Selection.Create(GetRootPart().Components[0]), None) options = LoftOptions() options.IsRuled = True selection = Selection.CreateByGroups("Right_elbow_in") selection += Selection.CreateByGroups("Right_connector_out") result = Loft.Create(selection, None, options) selection = Selection.Create(result.CreatedBodies[0]) result = ComponentHelper.MoveBodiesToComponent(selection) result.CreatedComponents[0].SetName("Right_connector") selection = Selection.CreateByGroups("Left_elbow_in") selection += Selection.CreateByGroups("Left_connector_out") result = Loft.Create(selection, None, options) selection = Selection.Create(result.CreatedBodies[0]) result = ComponentHelper.MoveBodiesToComponent(selection) result.CreatedComponents[0].SetName("Left_connector") #Simplify 1 body body = GetActivePart().GetAllComponents("Valve")[0].GetBodies()[0] zmax = 0 for face in body.Faces: if face.EvalMid().Point.Z > zmax: zmax = face.EvalMid().Point.Z my_face = face selection = Selection.Create(my_face) + Selection.Create(my_face.AdjacentFaces) result = Fill.Execute(selection) # Remove holes of radius 3mm sel = PowerSelection.Faces.BySurfaceHoleRadius(MM(3), PowerSelectOptions(False, BodySelection.Create(GetRootPart().Bodies[0])), SearchCriteria.SizeComparison.Equal) secondarySelection = Selection.Empty() options = FillOptions() result = Fill.Execute(sel, secondarySelection, options, FillMode.ThreeD) # Translate bigger hole Along X Handle circ_face = PowerSelection.Faces.BySurfaceHoleRadius(MM(35), PowerSelectOptions(False, BodySelection.Create(GetRootPart().Bodies[0])), SearchCriteria.SizeComparison.Equal) direction = Direction.Create(1, 0, 0) options = MoveOptions() result = Move.Translate(circ_face, direction, MM(45), options) # Translate (copy) bigger hole Along X Handle direction = Direction.Create(1, 0, 0) options = MoveOptions() options.CreatePatterns = True options.Copy = True result = Move.Translate(circ_face, direction, MM(-90), options) # Create Fluid Volume part = GetRootPart() body = part.Bodies[0] ymin = 0 ymax = 0 zmax = 0 # access faces with openings (ymin, ymax, zmax) for face in body.Faces: if face.EvalMid().Point.Y < ymin: ymin = face.EvalMid().Point.Y ymin_face = face if face.EvalMid().Point.Y > ymax: ymax = face.EvalMid().Point.Y ymax_face = face if face.EvalMid().Point.Z > zmax: zmax = face.EvalMid().Point.Z zmax_face = face options = VolumeExtractOptions() selection = FaceSelection.Create(ymin_face, ymax_face, zmax_face) #select seed face secondarySelection = circ_face result = VolumeExtract.Create(selection, secondarySelection, options) #----------------------------------EXTERNAL CONNECTIONS------------------------- #Reference to Microsoft Excel ClearAll() clr.AddReference("Microsoft.Office.Interop.Excel") import Microsoft.Office.Interop.Excel as Excel import os mypath = os.path.dirname(GetActiveWindow().Document.Path) myExcel = Excel.ApplicationClass() myExcel.Visible = True excel_file_name = "read_excel.xlsx" workbook = myExcel.Workbooks.Open(os.path.join(mypath,excel_file_name)) #or myWorkSheet = workbook.Worksheets("Sheet1") myWorkSheet = workbook.Worksheets[1] #Read data from Excel file i = 1 myX = "" wloc = True points = List[Point2D]() while wloc: myX = myWorkSheet.Rows[i].Value2[0,0] if not isinstance(myX, str): myY = myWorkSheet.Rows[i].Value2[0,1] points.Add(Point2D.Create(MM(myX), MM(myY))) i = i+1 if myX == "End": wloc = False workbook.Close() myExcel.Quit() #create spline curve from imported point data and create a surface body ViewHelper.SetSketchPlane(Plane.PlaneXY) result = SketchNurbs.CreateFrom2DPoints(True, points) ViewHelper.SetViewMode(InteractionMode.Solid) ViewHelper.ZoomToEntity()
The content on CFDyna.com is being constantly refined and improvised with on-the-job experience, testing, and training. Examples might be simplified to improve insight into the physics and basic understanding. Linked pages, articles, references, and examples are constantly reviewed to reduce errors, but we cannot warrant full correctness of all content.
Template by OS Templates