/***************************************************/ /**** Private methods ****/ /***************************************************/ private bool CreateObject(FEMesh fEMesh) { int uID = 1; int err = 0; int meshId = GetAdapterId <int>(fEMesh); int platePropId = GetAdapterId <int>(fEMesh.Property); // geometry List <int> nodesIds = fEMesh.Nodes.Select(nd => GetAdapterId <int>(nd)).ToList(); bool refresh = true; foreach (FEMeshFace fEMeshFace in fEMesh.Faces) { int plateId = (int)NextFreeId(typeof(FEMeshFace), refresh); refresh = false; SetAdapterId(fEMeshFace, plateId); int[] connectionNodes = new int[fEMeshFace.NodeListIndices.Count + 1]; connectionNodes[0] = fEMeshFace.NodeListIndices.Count; for (int i = 0; i < fEMeshFace.NodeListIndices.Count; i++) { connectionNodes[i + 1] = nodesIds[fEMeshFace.NodeListIndices[i]]; } err = St7.St7SetElementConnection(uID, St7.tyPLATE, plateId, platePropId, connectionNodes); } return(true); }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static FEMesh FEMesh(BH.oM.Geometry.Mesh mesh, ISurfaceProperty property = null, string name = null) { FEMesh feMesh = new FEMesh(); feMesh.Nodes = mesh.Vertices.Select(x => Node(x)).ToList(); foreach (Face face in mesh.Faces) { FEMeshFace feFace = new FEMeshFace(); feFace.NodeListIndices.Add(face.A); feFace.NodeListIndices.Add(face.B); feFace.NodeListIndices.Add(face.C); if (face.IsQuad()) { feFace.NodeListIndices.Add(face.D); } feMesh.MeshFaces.Add(feFace); } if (property != null) { feMesh.Property = property; } if (name != null) { feMesh.Name = name; } return(feMesh); }
/***************************************************/ public static Mesh Geometry(this FEMesh feMesh) { Mesh mesh = new Mesh(); mesh.Vertices = feMesh.Nodes.Select(x => x.Position()).ToList(); foreach (FEMeshFace feFace in feMesh.Faces) { if (feFace.NodeListIndices.Count < 3) { Reflection.Compute.RecordError("Insuffiecient node indices"); continue; } if (feFace.NodeListIndices.Count > 4) { Reflection.Compute.RecordError("To high number of node indices. Can only handle triangular and quads"); continue; } Face face = new Face(); face.A = feFace.NodeListIndices[0]; face.B = feFace.NodeListIndices[1]; face.C = feFace.NodeListIndices[2]; if (feFace.NodeListIndices.Count == 4) { face.D = feFace.NodeListIndices[3]; } mesh.Faces.Add(face); } return(mesh); }
public static Mesh Geometry(this FEMesh feMesh) { Mesh mesh = new Mesh(); mesh.Vertices = feMesh.Nodes.Select(x => x.Position).ToList(); mesh.Faces.AddRange(feMesh.Faces.Geometry()); return(mesh); }
public static FEMeshFace OrientTowards(this FEMeshFace face, FEMesh mesh, Point orientationPoint) { if (face.IsNull() || mesh.IsNull() || orientationPoint.IsNull()) { return(null); } Point centre = face.NodeListIndices.Select(i => mesh.Nodes[i].Position).Average(); Vector localX = (orientationPoint - centre).Normalise(); return(face.SetLocalOrientation(mesh, localX)); }
public static FEMesh OrientTowards(this FEMesh mesh, Point orientationPoint) { if (mesh.IsNull() || orientationPoint.IsNull()) { return(null); } FEMesh clone = mesh.ShallowClone(); clone.Faces = clone.Faces.Select(x => x.OrientTowards(mesh, orientationPoint)).ToList(); return(clone); }
public static FEMesh SetLocalOrientations(this FEMesh mesh, Vector localX) { if (mesh.IsNull() || localX.IsNull()) { return(null); } FEMesh clone = mesh.ShallowClone(); clone.Faces = clone.Faces.Select(x => x.SetLocalOrientation(mesh, localX)).ToList(); return(clone); }
/***************************************************/ /**** Private methods ****/ /***************************************************/ //The List<string> in the methods below can be changed to a list of any type of identification more suitable for the toolkit //If no ids are provided, the convention is to return all elements of the type private List <FEMesh> ReadMesh(List <int> ids = null) { // Just reading mesh without properties. Use all nodes. int uID = 1; int err = 0; int numberPlateElements = 0; err = St7.St7GetTotal(uID, St7.tyPLATE, ref numberPlateElements); if (!St7ErrorCustom(err, "Could not get total number of plate elements.")) { return(null); } List <Node> nodes = ReadNodes(); List <ISurfaceProperty> plateProps = ReadSurfaceProperty(); if (ids == null || ids.Count == 0) { ids = Enumerable.Range(1, numberPlateElements).ToList(); } FEMesh[] meshes = new FEMesh[plateProps.Count]; Dictionary <int, int> platePropsNumbers = new Dictionary <int, int>(); for (int i = 0; i < plateProps.Count; i++) { platePropsNumbers.Add(GetAdapterId <int>(plateProps[i]), i); meshes[i] = new FEMesh(); meshes[i].Nodes = nodes; meshes[i].Property = plateProps[i]; meshes[i].Name = plateProps[i].Name; SetAdapterId(meshes[i], i); } foreach (int id in ids) { int platePropNum = 0; err = St7.St7GetElementProperty(uID, St7.ptPLATEPROP, id, ref platePropNum); int propIndex = platePropsNumbers[platePropNum]; FEMeshFace face = new FEMeshFace(); SetAdapterId(face, id); int[] plateConnection = new int[St7.kMaxElementNode + 1]; err = St7.St7GetElementConnection(uID, St7.tyPLATE, id, plateConnection); if (plateConnection[0] == 3 || plateConnection[0] == 6) // Plate elements Tri3 and Tri6. Firt index is a number of vertices { face.NodeListIndices = new int[] { plateConnection[1] - 1, plateConnection[2] - 1, plateConnection[3] - 1 }.ToList(); } else // All quad elements { face.NodeListIndices = new int[] { plateConnection[1] - 1, plateConnection[2] - 1, plateConnection[3] - 1, plateConnection[4] - 1 }.ToList(); } meshes[propIndex].Faces.Add(face); } return(meshes.ToList()); }
public static bool IsNull(this FEMesh mesh, bool checkFaces = true, bool checkNodes = true, List <int> nodeListIndices = null, string msg = "", [CallerMemberName] string methodName = "Method") { // Check FEMesh if (mesh == null) { ErrorMessage(methodName, "FEMesh", msg); return(true); } else if (mesh.Faces == null || mesh.Faces.Count == 0) { Reflection.Compute.RecordError($"Cannot evaluate {methodName} because the list of Faces are null or the number of Faces is 0. {msg}"); return(true); } else if (mesh.Nodes == null || mesh.Nodes.Count == 0) { Reflection.Compute.RecordError($"Cannot evaluate {methodName} because the list of Nodes are null or the number of Nodes is 0. {msg}"); return(true); } // Make sure to check all mesh Nodes if none are specified // When called from the FEMeshFace version of this method, we limit the Node check to relevant Nodes if (checkNodes && (nodeListIndices == null || nodeListIndices.Count == 0)) { nodeListIndices = new List <int>(); nodeListIndices.AddRange(Enumerable.Range(0, mesh.Nodes.Count - 1)); } // If mesh nodes are specified, check that they are in range else if (checkNodes && mesh.Nodes.Count - 1 < nodeListIndices.Max()) { Reflection.Compute.RecordError($"Cannot evaluate {methodName} because Node indices are out of range for FEMesh"); return(false); } // Check Nodes, but only if checkNodes is set to true // When called from methods that run on the list of mesh FEMeshFaces, we only want a basic check as null checks will be performed individually for each face bool isNull = false; for (int i = 0; checkNodes && !isNull && i < nodeListIndices.Count; i++) { isNull = mesh.Nodes[nodeListIndices[i]].IsNull($"The Node is owned by an FEMesh. {msg}", methodName); } // Check FEMeshFaces, but only if checkFaces is set to true // When called from the FEMeshFace version of this method, we do not need to check FEMeshFaces, as the only relevant face has already been checked for (int i = 0; checkFaces && !isNull && i < mesh.Faces.Count; i++) { isNull = mesh.Faces[i].IsNull($"The FEMeshFace is owned by an FEMesh. {msg}", methodName); } return(isNull); }
public static List <Panel> FEMeshToPanel(this FEMesh feMesh) { if (feMesh.IsNull()) { return(null); } if (feMesh.Nodes.Count < 3) { Reflection.Compute.RecordError("Insufficient number of nodes to be able to convert FEMesh to a Panel."); return(null); } if (feMesh.Faces.Count < 1) { Reflection.Compute.RecordError("At least one FEFace required to construct a Panel from FEMesh."); return(null); } List <Polyline> polylines = new List <Polyline>(); foreach (FEMeshFace feMeshFace in feMesh.Faces) { List <Point> points = new List <Point>(); foreach (int nodeIndex in feMeshFace.NodeListIndices) { points.Add(feMesh.Nodes[nodeIndex].Position); } points.Add(feMesh.Nodes[feMeshFace.NodeListIndices.First()].Position); polylines.Add(Geometry.Create.Polyline(points)); } List <Panel> panels = new List <Panel>(); Panel panel = new Panel(); foreach (Polyline polyline in polylines) { panel = Create.Panel(polyline, null, null, feMesh.Name); if (feMesh.Property != null) { panel.Property = feMesh.Property; } if (feMesh.Fragments.Count > 0) { panel.Fragments = feMesh.Fragments; } if (feMesh.Tags.Count > 0) { panel.Tags = feMesh.Tags; } panels.Add(panel); } return(panels); }
public static bool IsNull(this FEMeshFace face, FEMesh mesh, string msg = "", [CallerMemberName] string methodName = "Method") { // Check FEMeshFace and relevant nodes in FEMesh if (face.IsNull(msg, methodName)) { return(true); } else if (mesh.IsNull(false, true, face.NodeListIndices, msg, methodName)) { return(true); } return(false); }
private int addElementToGroup(int uID, int groupID, FEMesh feMesh) { int err = 0; foreach (FEMeshFace fEMeshFace in feMesh.Faces) { int plateId = GetAdapterId <int>(fEMeshFace); err = St7.St7SetEntityGroup(uID, St7.tyPLATE, plateId, groupID); if (!St7Error(err)) { return(err); } } return(0); }
/***************************************************/ private static Mesh DeformedMesh(FEMesh feMesh, IEnumerable <MeshDisplacement> disps, string adapterId, double scaleFactor) { Mesh mesh = new Mesh(); foreach (Node node in feMesh.Nodes) { MeshDisplacement disp = disps.FirstOrDefault(x => x.NodeId.ToString() == node.CustomData[adapterId].ToString()); if (disp == null) { Reflection.Compute.RecordError("Could not find displacement for node with adapter Id: " + node.CustomData[adapterId].ToString() + ", from mesh with Id: " + feMesh.CustomData[adapterId].ToString()); return(new Mesh()); } Vector dispVector = disp.CoordinateSystem.X * disp.UXX * scaleFactor + disp.CoordinateSystem.Y * disp.UYY * scaleFactor + disp.CoordinateSystem.Z * disp.UZZ * scaleFactor; mesh.Vertices.Add(node.Position() + dispVector); } foreach (FEMeshFace feFace in feMesh.MeshFaces) { if (feFace.NodeListIndices.Count < 3) { Reflection.Compute.RecordError("Insuffiecient node indices"); continue; } if (feFace.NodeListIndices.Count > 4) { Reflection.Compute.RecordError("To high number of node indices. Can only handle triangular and quads"); continue; } Face face = new Face(); face.A = feFace.NodeListIndices[0]; face.B = feFace.NodeListIndices[1]; face.C = feFace.NodeListIndices[2]; if (feFace.NodeListIndices.Count == 4) { face.D = feFace.NodeListIndices[3]; } mesh.Faces.Add(face); } return(mesh); }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static Mesh MeshFromFEMesh(this FEMesh feMesh, bool clean) { Dictionary <int, int> indicesUsed = new Dictionary <int, int>(); Mesh mesh = new Mesh(); int fcA = 0; int fcB = 0; int fcC = 0; int fcD = 0; foreach (var feFace in feMesh.Faces) { Face face = new Face(); if (feFace.NodeListIndices.Count == 3) // Plate elements Tri3 and Tri6. Firt index is a number of vertices { fcA = feFace.NodeListIndices[0]; fcB = feFace.NodeListIndices[1]; fcC = feFace.NodeListIndices[2]; face.A = clean ? AddItemToListAndReturnIndex(indicesUsed, fcA) : fcA; face.B = clean ? AddItemToListAndReturnIndex(indicesUsed, fcB) : fcB; face.C = clean ? AddItemToListAndReturnIndex(indicesUsed, fcC) : fcC; } else // All quad elements { fcA = feFace.NodeListIndices[0]; fcB = feFace.NodeListIndices[1]; fcC = feFace.NodeListIndices[2]; fcD = feFace.NodeListIndices[3]; face.A = clean ? AddItemToListAndReturnIndex(indicesUsed, fcA) : fcA; face.B = clean ? AddItemToListAndReturnIndex(indicesUsed, fcB) : fcB; face.C = clean ? AddItemToListAndReturnIndex(indicesUsed, fcC) : fcC; face.D = clean ? AddItemToListAndReturnIndex(indicesUsed, fcD) : fcD; } mesh.Faces.Add(face); } // creating a list of used Vertices if (clean) { mesh.Vertices = indicesUsed.Select(x => feMesh.Nodes[x.Key].Position).ToList(); } else { mesh.Vertices = feMesh.Nodes.Select(nd => nd.Position).ToList(); } return(mesh); }
public static FEMesh FEMesh(Mesh mesh, ISurfaceProperty property = null, Vector localX = null, string name = null) { if (mesh.IsNull()) { return(null); } FEMesh feMesh = new FEMesh(); feMesh.Nodes = mesh.Vertices.Select(x => Node(x)).ToList(); foreach (Face face in mesh.Faces) { FEMeshFace feFace = new FEMeshFace(); feFace.NodeListIndices.Add(face.A); feFace.NodeListIndices.Add(face.B); feFace.NodeListIndices.Add(face.C); if (face.IsQuad()) { feFace.NodeListIndices.Add(face.D); } feMesh.Faces.Add(feFace); } if (property != null) { feMesh.Property = property; } if (name != null) { feMesh.Name = name; } if (localX != null) { return(feMesh.SetLocalOrientations(localX)); } else { return(feMesh); } }
public static FEMeshFace SetLocalOrientation(this FEMeshFace face, FEMesh mesh, Vector localX) { if (face.IsNull() || mesh.IsNull() || localX.IsNull()) { return(null); } FEMeshFace clone = face.ShallowClone(); Vector normal = face.Normal(mesh); double orientationAngle = Compute.OrientationAngleAreaElement(normal, localX); if (!double.IsNaN(orientationAngle)) { clone.OrientationAngle = orientationAngle; } return(clone); }
/***************************************************/ private static List <List <ICurve> > SubElementBoundaries(FEMesh element) { List <List <ICurve> > elementCurves = new List <List <ICurve> >(); foreach (FEMeshFace face in element.Faces) { List <ICurve> faceEdges = new List <ICurve>(); for (int i = 0; i < face.NodeListIndices.Count; i++) { int next = (i + 1) % face.NodeListIndices.Count; Line edge = new Line { Start = element.Nodes[face.NodeListIndices[i]].Position, End = element.Nodes[face.NodeListIndices[next]].Position }; faceEdges.Add(edge); } elementCurves.Add(faceEdges); } return(elementCurves); }
public static List <Point> PointGrid(this FEMeshFace face, FEMesh mesh) { if (face.IsNull() || mesh.IsNull()) { return(null); } List <Point> pts = face.NodeListIndices.Select(i => mesh.Nodes[i].Position).ToList(); List <Point> temp = new List <Point>(); for (int i = 0; i < pts.Count; i++) { int next = (i + 1) % pts.Count; temp.Add((pts[i] + pts[next]) / 2); } pts.AddRange(temp); pts.Add(pts.Average()); return(pts); }
public static FEMesh Transform(this FEMesh mesh, TransformMatrix transform, double tolerance = Tolerance.Distance) { if (!transform.IsRigidTransformation(tolerance)) { BH.Engine.Reflection.Compute.RecordError("Transformation failed: only rigid body transformations are currently supported."); return(null); } FEMesh result = mesh.ShallowClone(); result.Nodes = result.Nodes.Select(x => x.Transform(transform, tolerance)).ToList(); List <Basis> orientationsBefore = mesh.LocalOrientations(); result.Faces = new List <FEMeshFace>(mesh.Faces); for (int i = 0; i < orientationsBefore.Count; i++) { result.Faces[i] = result.Faces[i].SetLocalOrientation(result, orientationsBefore[i].Transform(transform).X); } return(result); }
public static Vector Normal(this FEMeshFace face, FEMesh mesh) { if (face.IsNull(mesh)) { return(null); } if (face.NodeListIndices.Count < 3) { Engine.Reflection.Compute.RecordError("Face has insufficient number of nodes to calculate normal."); return(null); } else if (face.NodeListIndices.Count > 4) { Engine.Reflection.Compute.RecordError("Can only determine normal from 3 or 4 sided faces."); return(null); } Point pA = mesh.Nodes[face.NodeListIndices[0]].Position; Point pB = mesh.Nodes[face.NodeListIndices[1]].Position; Point pC = mesh.Nodes[face.NodeListIndices[2]].Position; Vector normal; if (face.NodeListIndices.Count == 3) { normal = Engine.Geometry.Query.CrossProduct(pB - pA, pC - pB); } else { Point pD = mesh.Nodes[face.NodeListIndices[3]].Position; normal = (Engine.Geometry.Query.CrossProduct(pA - pD, pB - pA)) + (Engine.Geometry.Query.CrossProduct(pC - pB, pD - pC)); } return(normal.Normalise()); }
/***************************************************/ private static List <List <Point> > SubElementPointGrids(FEMesh element) { return(element.PointGrid()); }
/***************************************************/ public static double Area(this FEMesh mesh) { return(mesh.Geometry().Area()); }
public static Cartesian CoordinateSystem(this FEMeshFace face, FEMesh mesh) { Basis orientation = face?.LocalOrientation(mesh); return(orientation != null ? new Cartesian(face.NodeListIndices.Select(i => mesh.Nodes[i].Position).Average(), orientation.X, orientation.Y, orientation.Z) : null); }
/***************************************************/ private List <FEMesh> ReadMesh(List <string> ids = null) { List <Panel> panelList = new List <Panel>(); int nameCount = 0; string[] nameArr = { }; m_model.AreaObj.GetNameList(ref nameCount, ref nameArr); ids = FilterIds(ids, nameArr); List <FEMesh> meshes = new List <FEMesh>(); Dictionary <string, Node> nodes = new Dictionary <string, Node>(); Dictionary <string, ISurfaceProperty> surfaceProps = ReadSurfaceProperty().ToDictionary(x => GetAdapterId <string>(x)); foreach (string id in ids) { FEMesh mesh = new FEMesh(); ETABSId etabsid = new ETABSId(); etabsid.Id = id; List <string> meshNodeIds = new List <string>(); //Get out the "Element" ids, i.e. the mesh faces int nbELem = 0; string[] elemNames = new string[0]; m_model.AreaObj.GetElm(id, ref nbELem, ref elemNames); for (int j = 0; j < nbELem; j++) { //Get out the name of the points for each face int nbPts = 0; string[] ptsNames = new string[0]; m_model.AreaElm.GetPoints(elemNames[j], ref nbPts, ref ptsNames); FEMeshFace face = new FEMeshFace(); for (int k = 0; k < nbPts; k++) { string nodeId = ptsNames[k]; Node node; //Check if node already has been pulled if (!nodes.TryGetValue(nodeId, out node)) { double x = 0, y = 0, z = 0; m_model.PointElm.GetCoordCartesian(nodeId, ref x, ref y, ref z); node = new Node() { Position = new Point { X = x, Y = y, Z = z } }; SetAdapterId(node, nodeId); nodes[ptsNames[k]] = node; } //Check if nodealready has been added to the mesh if (!meshNodeIds.Contains(nodeId)) { meshNodeIds.Add(nodeId); } //Get corresponding node index face.NodeListIndices.Add(meshNodeIds.IndexOf(nodeId)); } //Add face to list SetAdapterId(face, elemNames[j]); mesh.Faces.Add(face); } //Set mesh nodes - if there are no nodes, don't create the mesh. if (nodes.Count != 0 && mesh.Faces.Count != 0) { mesh.Nodes = meshNodeIds.Select(x => nodes[x]).ToList(); string propertyName = ""; m_model.AreaObj.GetProperty(id, ref propertyName); if (propertyName != "None") { mesh.Property = surfaceProps[propertyName]; } //Get local x-axis double orientation = 0; bool advanced = false; m_model.AreaObj.GetLocalAxes(id, ref orientation, ref advanced); Vector normal = mesh.Faces.First().Normal(mesh); //Assuming flat mesh, all normals equal Vector localX = Convert.FromCSILocalX(normal, orientation); mesh = mesh.SetLocalOrientations(localX); //Label and story string label = ""; string story = ""; if (m_model.AreaObj.GetLabelFromName(id, ref label, ref story) == 0) { etabsid.Label = label; etabsid.Story = story; } // Get guid string guid = null; m_model.AreaObj.GetGUID(id, ref guid); etabsid.PersistentId = guid; SetAdapterId(mesh, etabsid); meshes.Add(mesh); } else { BH.Engine.Base.Compute.RecordWarning("Mesh " + id.ToString() + " could not be pulled, because it contains no nodes"); } } return(meshes); }
public static double Area(this FEMesh mesh) { return(mesh.IsNull() ? 0 : Analytical.Query.Geometry(mesh).Area()); }
public static List <List <Point> > PointGrid(this FEMesh mesh) { return(mesh.IsNull() ? null : mesh.Faces.Select(x => x.PointGrid(mesh)).ToList()); }
public static List <Basis> LocalOrientations(this FEMesh mesh) { return(mesh.IsNull() ? null : mesh.Faces.Select(x => x.LocalOrientation(mesh)).ToList()); }
public static Basis LocalOrientation(this FEMeshFace face, FEMesh mesh) { return(face.IsNull(mesh) ? null : LocalOrientation(face.Normal(mesh), face.OrientationAngle)); }
/***************************************************/ private static List <Basis> AllLocalOrientations(FEMesh element) { return(element.LocalOrientations()); }
public static List <Vector> Normals(this FEMesh mesh) { return(mesh.IsNull() ? null : mesh.Faces.Select(x => x.Normal(mesh)).ToList()); }