public void Difference() { this.Name = "CSG_Difference"; var profile = _profileFactory.GetProfileByType(HSSPipeProfileType.HSS10_000x0_188); var path = new Arc(Vector3.Origin, 5, 0, 270); var s1 = new Sweep(profile, path, 0, 0, 0, true); var csg = s1.Solid.ToCsg(); var s2 = new Extrude(new Circle(Vector3.Origin, 6).ToPolygon(20), 1, Vector3.ZAxis, false); csg = csg.Substract(s2.Solid.ToCsg()); for (var i = 0.0; i < 1.0; i += 0.05) { var pt = path.PointAt(i); var hole = new Extrude(new Circle(Vector3.Origin, 0.05).ToPolygon(), 3, Vector3.ZAxis, false); csg = csg.Substract(hole.Solid.ToCsg().Transform(new Transform(pt + new Vector3(0, 0, -2)).ToMatrix4x4())); } var result = new Mesh(); csg.Tessellate(ref result); var me2 = new MeshElement(result); this.Model.AddElement(me2); }
private MeshElement ConstructExampleMesh() { var mesh = new Mesh(); var gridSize = 10; for (var u = 0; u < gridSize; u += 1) { for (var v = 0; v < gridSize; v += 1) { var sinu = Math.Sin(-Math.PI + 2 * ((double)u / (double)gridSize * Math.PI)); var sinv = Math.Sin(-Math.PI + 2 * ((double)v / (double)gridSize * Math.PI)); var z = sinu + sinv; var vertex = new Geometry.Vertex(new Vector3(u, v, z), color: Colors.Mint); mesh.AddVertex(vertex); if (u > 0 && v > 0) { var index = u * gridSize + v; var a = mesh.Vertices[index]; var b = mesh.Vertices[index - gridSize]; var c = mesh.Vertices[index - 1]; var d = mesh.Vertices[index - gridSize - 1]; var tri1 = new Triangle(a, b, c); var tri2 = new Triangle(c, b, d); mesh.AddTriangle(tri1); mesh.AddTriangle(tri2); } } } mesh.ComputeNormals(); var meshElement = new MeshElement(mesh, new Material("Lime", Colors.Lime), new Transform(new Vector3(-7, -8, 0), new Vector3(-5, 3, 2))); return(meshElement); }
/// <summary> /// The RhinoComputeExample function. /// </summary> /// <param name="model">The input model.</param> /// <param name="input">The arguments to the execution.</param> /// <returns>A RhinoComputeExampleOutputs instance containing computed results and the model with any new elements.</returns> public static RhinoComputeExampleOutputs Execute(Dictionary <string, Model> inputModels, RhinoComputeExampleInputs input) { // set up a model to hold elements var model = new Model(); // Call rhino methods with regular rhino calls, or Rhino.Compute calls if required methods are unavailable var box1 = rg.Brep.CreateFromBox(new rg.BoundingBox(new rg.Point3d(0, 0, 0), new rg.Point3d(input.Radius, input.Radius, input.Radius))); var box2 = rg.Brep.CreateFromBox(new rg.BoundingBox(new rg.Point3d(input.Radius * 0.5, input.Radius * 0.5, input.Radius * 0.5), new rg.Point3d(input.Radius * 1.5, input.Radius * 1.5, input.Radius * 1.5))); var booleanDiff = Rhino.Compute.BrepCompute.CreateBooleanDifference(box1, box2, 0.1).First(); var boundaryCurves = booleanDiff.Faces.Select(f => f.OuterLoop.To3dCurve()); // Use conversion extension methods from HyRhi / Conversion.cs var elementsSphereMesh = booleanDiff.ToMesh(); var elementsCrvs = boundaryCurves.Select(c => c.ToPolygon()); // create Hypar Elements from resulting geometry var meshElement = new MeshElement(elementsSphereMesh, BuiltInMaterials.Glass); var curveElements = elementsCrvs.Select(c => new ModelCurve(c)); // add elements to model model.AddElement(meshElement); model.AddElements(curveElements); // construct output object var output = new RhinoComputeExampleOutputs(); // add model to output output.Model = model; // return output return(output); }
public static Vector3 MeshCentroid(MeshElement mesh) { var verts = mesh.Mesh.Vertices; var centroid = AverageVert(verts); return(centroid); }
public bool start(string path) { if (Provider.Provider.OpenConnection()) { if (Provider.Provider.openProject(path)) { Element elems = new Element(); elems.saveToDataBase(elems.getData(), new element(), new DataModel()); MeshPoint nodes = new MeshPoint(); nodes.saveToDataBase(nodes.getData(), new nodes(), new DataModel()); Moments mts = new Moments(); mts.saveToDataBase(mts.getData(), new moment(), new DataModel()); MeshElement element = new MeshElement(); element.saveToDataBase(element.getData(), new meshele(), new DataModel()); Provider.Provider.CloseConnection(); return(true); } else { MessageBox.Show("Nie wczytano pliku ..."); return(false); } } else { MessageBox.Show("Nie polaczono ..."); return(false); } }
private SolidAnalysisObject(MeshElement meshElement) { Dictionary <string, long> edgeLookup = new Dictionary <string, long>(); long edgeIdx = 0; foreach (var vertex in meshElement.Mesh.Vertices) { var key = vertex.Index; var point = GeoUtilities.TransformedPoint(vertex.Position, meshElement.Transform); this.Points.Add(key, point); this._maxVertexKey = Math.Max(this._maxVertexKey, key); } var tIdx = 0; foreach (var triangle in meshElement.Mesh.Triangles) { var vertices = triangle.Vertices.ToList(); var edges = new List <AnalysisEdge>(); var vIdx = 0; // Only add points where face is not sitting on Z = 0 var pointNotZero = false; foreach (var startVertex in vertices) { var endVertex = vIdx == vertices.Count - 1 ? vertices[0] : vertices[vIdx + 1]; var lowerVertex = startVertex.Index < endVertex.Index ? startVertex : endVertex; var higherVertex = startVertex.Index > endVertex.Index ? startVertex : endVertex; var lineIdUniq = $"{lowerVertex.Index}_{higherVertex.Index}"; pointNotZero = pointNotZero || (this.Points[lowerVertex.Index].Z != 0.0 || this.Points[higherVertex.Index].Z != 0.0); if (!edgeLookup.ContainsKey(lineIdUniq)) { this.AddEdge(edgeIdx, lowerVertex.Index, higherVertex.Index); edgeLookup.Add(lineIdUniq, edgeIdx); edgeIdx += 1; } if (edgeLookup.TryGetValue(lineIdUniq, out long addedOrExistingEdgeIdx)) { var isReversed = startVertex.Index != lowerVertex.Index; edges.Add(new AnalysisEdge(addedOrExistingEdgeIdx, isReversed)); } vIdx += 1; } if (pointNotZero) { this.Surfaces.Add(edges); } tIdx += 1; } }
public void NodeInterpolationTest(string meshFileName, CircularValueTypes cvt = CircularValueTypes.Normal) { // Source mesh MeshFile meshFile = MeshFile.ReadMesh(meshFileName); MeshData mesh = meshFile.ToMeshData(); // Allow for extrapolation on boundary nodes (disable clipping) MeshNodeInterpolation interpolation = new MeshNodeInterpolation(mesh) { AllowExtrapolation = true, }; interpolation.Setup(); Interpolator nodeInterpolator = interpolation.NodeInterpolator; nodeInterpolator.CircularType = cvt; // Find reference x and y value as the smallest x and y value double xMin = mesh.Nodes.Select(mn => mn.X).Min(); double xMax = mesh.Nodes.Select(mn => mn.X).Max(); double yMin = mesh.Nodes.Select(mn => mn.Y).Min(); double yMax = mesh.Nodes.Select(mn => mn.Y).Max(); // Function over the (x,y) plane. Func <double, double, double> function = ValueFunction(cvt, xMin, yMin, xMax, yMax); // Calculate element center values double[] elmtVals = new double[mesh.Elements.Count]; for (int i = 0; i < mesh.Elements.Count; i++) { MeshElement elmt = mesh.Elements[i]; elmtVals[i] = function(elmt.XCenter, elmt.YCenter); } // Write out bounds, to check we got things right Console.Out.WriteLine("{0,10} (min,max) = ({1},{2})", cvt, elmtVals.Min(), elmtVals.Max()); // Interpolate to nodes double[] nodeValues = new double[mesh.Nodes.Count]; nodeInterpolator.Interpolate(elmtVals, nodeValues); // Check node values for (int i = 0; i < mesh.Nodes.Count; i++) { MeshNode node = mesh.Nodes[i]; double exactValue = function(node.X, node.Y); double interpValue = nodeValues[i]; double diff = exactValue - interpValue; // It can only extrapolate when there is at least three elements per node. // When there is two or less elements, the inverse distance weighting takes over // and the results are not correct, so we skip the check here. if (node.Elements.Count > 2 && diff > 1e-6) { string msg = string.Format("{0,2} {6}: {1}-{2}={3} ({4},{5})", i, exactValue, interpValue, diff, node.X, node.Y, node.Elements.Count); Console.Out.WriteLine(msg); Assert.Fail(msg); } } }
protected override bool ImportStandtradShapeData() { var MeshPolygons = MeshElement.Sphere(0.5); for (int i = 0; i < MeshPolygons.Length; i++) { //GL.Normal3(MeshPolygons[i].Normal); for (int j = 0; j < MeshPolygons[i].Vertices.Length; j++) { LocalVertices.Add(MeshPolygons[i].Vertices[j]); } } return(base.ImportStandtradShapeData()); }
public void Union() { this.Name = "CSG_Union"; var s1 = new Extrude(Polygon.Rectangle(1, 1), 1, Vector3.ZAxis, false); var csg = s1.Solid.ToCsg(); var s2 = new Extrude(Polygon.L(1.0, 2.0, 0.5), 1, Vector3.ZAxis, false); csg = csg.Union(s2.Solid.ToCsg()); var result = new Mesh(); csg.Tessellate(ref result); var me = new MeshElement(result); this.Model.AddElement(me); }
public static List <Envelope> SliceAtHeight(MeshElement meshElement, double cutHeight, Boolean showDebugGeometry) { var bbox = new BBox3(TransformedVertices(meshElement.Mesh.Vertices, meshElement.Transform)); var bottom = bbox.Min.Z; var top = bbox.Max.Z; var solids = new List <Elements.Geometry.Solids.SolidOperation>(); var solid = new Elements.Geometry.Solids.Solid(); foreach (var face in meshElement.Mesh.Triangles) { var vertices = TransformedVertices(face.Vertices, meshElement.Transform); solid.AddFace(new Polygon(vertices)); } solids.Add(new Elements.Geometry.Solids.ConstructedSolid(solid)); var rep = new Representation(solids); var env = new Envelope(Polygon.Rectangle(new Vector3(bbox.Min.X, bbox.Min.Y), new Vector3(bbox.Max.X, bbox.Max.Y)), bottom, top - bottom, Vector3.ZAxis, 0, new Transform(), _debugMaterial, rep, false, Guid.NewGuid(), ""); return(SliceAtHeight(env, cutHeight, showDebugGeometry)); }
public void ElementIncludesTest() { MeshElement element = new MeshElement(); element.Nodes = new List <MeshNode>(3); element.Nodes.Add(new MeshNode() { X = 1.1, Y = 1.0 }); element.Nodes.Add(new MeshNode() { X = 2.2, Y = 1.1 }); element.Nodes.Add(new MeshNode() { X = 1.6, Y = 2.0 }); // Corner points are inside Assert.True(element.Includes(1.1, 1.0)); Assert.True(element.Includes(2.2, 1.1)); Assert.True(element.Includes(1.6, 2.0)); // Points on face lines are inside // Mid point, first face Assert.True(element.Includes(1.65, 1.05)); Assert.True(element.Includes(1.65, 1.05 + 0.0000001)); Assert.False(element.Includes(1.65, 1.05 - 0.0000001)); // Mid point, second face Assert.True(element.Includes(1.9, 1.55)); Assert.True(element.Includes(1.9, 1.55 - 0.00000001)); Assert.False(element.Includes(1.9, 1.55 + 0.00000001)); // Mid point, third face Assert.True(element.Includes(1.35, 1.5)); Assert.True(element.Includes(1.35, 1.5 - 0.000000001)); Assert.False(element.Includes(1.35, 1.5 + 0.000000001)); }
public void MeshElement() { this.Name = "Elements_MeshElement"; // <example> var mesh = new Mesh(); var gridSize = 10; for (var u = 0; u < gridSize; u += 1) { for (var v = 0; v < gridSize; v += 1) { var sinu = Math.Sin(-Math.PI + 2 * ((double)u / (double)gridSize * Math.PI)); var sinv = Math.Sin(-Math.PI + 2 * ((double)v / (double)gridSize * Math.PI)); var z = sinu + sinv; var vertex = new Vertex(new Vector3(u, v, z), color: Colors.Mint); mesh.AddVertex(vertex); if (u > 0 && v > 0) { var index = u * gridSize + v; var a = mesh.Vertices[index]; var b = mesh.Vertices[index - gridSize]; var c = mesh.Vertices[index - 1]; var d = mesh.Vertices[index - gridSize - 1]; var tri1 = new Triangle(a, b, c); var tri2 = new Triangle(c, b, d); mesh.AddTriangle(tri1); mesh.AddTriangle(tri2); } } } mesh.ComputeNormals(); var meshElement = new MeshElement(mesh, new Material("Lime", Colors.Lime)); //</example> this.Model.AddElement(meshElement); }
public Dictionary <string, object> Handler(Dictionary <string, object> input, ILambdaContext context) { var width = float.Parse(input["width"].ToString()); var height = float.Parse(input["height"].ToString()); var aspect_ratio = float.Parse(input["aspectRatio"].ToString()); var features = ((JArray)input["boundary"]).ToObject <Feature[]>(); var outline = (Polygon)features[0].Geometry; var origin = outline.Coordinates[0][0]; var offset = origin.ToVectorMeters(); var plines = outline.ToPolylines(); var pline = plines[0]; var boundary = new Polyline(pline.Vertices.Select(v => new Vector3(v.X - offset.X, v.Y - offset.Y, v.Z))); var building = Building.Make(boundary.ToArray(), width, height, aspect_ratio); var model = new Model(); model.Origin = origin; var mesh = new MeshElement(Mesh.Extrude(building.Polylines, height)); model.AddElement(mesh); return(model.ToHypar()); }
public void Test() { Vector3[] boundary = { new Vector3(0.0f, 0.0f), new Vector3(200.0f, 0.0f), new Vector3(200.0f, 200.0f), new Vector3(0.0f, 200.0f), }; var height = 40.0f; var building = Building.Make(boundary, 60.0f, height, 0.5f); for (int i = 0; i < building.Polylines.Count; ++i) { Console.WriteLine(building.Polylines[i].ToString()); } var model = new Model(); var mesh = new MeshElement(Mesh.Extrude(building.Polylines, height)); model.AddElement(mesh); model.SaveGlb("test.glb"); }
void UpdateAnimation() { if (loaded && a3d != null && channelObjects != null & subObjects != null) { if (currentFrame >= a3d.num_onlyFrames) { currentFrame %= a3d.num_onlyFrames; } // First pass: reset TRS for all sub objects for (int i = 0; i < channelParents.Length; i++) { channelParents[i] = false; } AnimOnlyFrame of = a3d.onlyFrames[a3d.start_onlyFrames + currentFrame]; // Create hierarchy for this frame for (int i = of.start_hierarchies_for_frame; i < of.start_hierarchies_for_frame + of.num_hierarchies_for_frame; i++) { AnimHierarchy h = a3d.hierarchies[i]; if (Controller.Settings.engineVersion <= Settings.EngineVersion.TT) { channelObjects[h.childChannelID].transform.SetParent(channelObjects[h.parentChannelID].transform); channelParents[h.childChannelID] = true; } else { if (!channelIDDictionary.ContainsKey(h.childChannelID) || !channelIDDictionary.ContainsKey(h.parentChannelID)) { continue; } List <int> ch_child_list = GetChannelByID(h.childChannelID); List <int> ch_parent_list = GetChannelByID(h.parentChannelID); foreach (int ch_child in ch_child_list) { foreach (int ch_parent in ch_parent_list) { channelObjects[ch_child].transform.SetParent(channelObjects[ch_parent].transform); channelParents[ch_child] = true; } } } //channelObjects[ch_child].transform.SetParent(channelObjects[ch_parent].transform); } // Final pass for (int i = 0; i < a3d.num_channels; i++) { AnimChannel ch = a3d.channels[a3d.start_channels + i]; AnimFramesKFIndex kfi = a3d.framesKFIndex[currentFrame + ch.framesKF]; AnimKeyframe kf = a3d.keyframes[kfi.kf]; AnimVector pos = a3d.vectors[kf.positionVector]; AnimQuaternion qua = a3d.quaternions[kf.quaternion]; AnimVector scl = a3d.vectors[kf.scaleVector]; AnimNumOfNTTO numOfNTTO = a3d.numOfNTTO[ch.numOfNTTO + of.numOfNTTO]; AnimNTTO ntto = a3d.ntto[numOfNTTO.numOfNTTO]; //if (ntto.IsBoneNTTO) continue; int poNum = numOfNTTO.numOfNTTO - a3d.start_NTTO; PhysicalObject physicalObject = subObjects[i][poNum]; Vector3 vector = pos.vector; Quaternion quaternion = qua.quaternion; Vector3 scale = scl.vector; int framesSinceKF = (int)currentFrame - (int)kf.frame; AnimKeyframe nextKF = null; int framesDifference; float interpolation; if (kf.IsEndKeyframe) { AnimFramesKFIndex next_kfi = a3d.framesKFIndex[0 + ch.framesKF]; nextKF = a3d.keyframes[next_kfi.kf]; framesDifference = a3d.num_onlyFrames - 1 + (int)nextKF.frame - (int)kf.frame; if (framesDifference == 0) { interpolation = 0; } else { //interpolation = (float)(nextKF.interpolationFactor * (framesSinceKF / (float)framesDifference) + 1.0 * nextKF.interpolationFactor); interpolation = framesSinceKF / (float)framesDifference; } } else { nextKF = a3d.keyframes[kfi.kf + 1]; framesDifference = (int)nextKF.frame - (int)kf.frame; //interpolation = (float)(nextKF.interpolationFactor * (framesSinceKF / (float)framesDifference) + 1.0 * nextKF.interpolationFactor); interpolation = framesSinceKF / (float)framesDifference; } //print(interpolation); //print(a3d.vectors.Length + " - " + nextKF.positionVector); AnimVector pos2 = a3d.vectors[nextKF.positionVector]; AnimQuaternion qua2 = a3d.quaternions[nextKF.quaternion]; AnimVector scl2 = a3d.vectors[nextKF.scaleVector]; vector = Vector3.Lerp(pos.vector, pos2.vector, interpolation); quaternion = Quaternion.Lerp(qua.quaternion, qua2.quaternion, interpolation); scale = Vector3.Lerp(scl.vector, scl2.vector, interpolation); float positionMultiplier = Mathf.Lerp(kf.positionMultiplier, nextKF.positionMultiplier, interpolation); if (poNum != currentActivePO[i]) { if (currentActivePO[i] == -2 && fullMorphPOs != null && fullMorphPOs[i] != null) { foreach (PhysicalObject morphPO in fullMorphPOs[i].Values) { if (morphPO.Gao.activeSelf) { morphPO.Gao.SetActive(false); } } } if (currentActivePO[i] >= 0 && subObjects[i][currentActivePO[i]] != null) { subObjects[i][currentActivePO[i]].Gao.SetActive(false); } currentActivePO[i] = poNum; if (physicalObject != null) { physicalObject.Gao.SetActive(true); } } if (!channelParents[i]) { channelObjects[i].transform.SetParent(perso.gameObject.transform); } channelObjects[i].transform.localPosition = vector * positionMultiplier; channelObjects[i].transform.localRotation = quaternion; channelObjects[i].transform.localScale = scale; if (physicalObject != null && a3d.num_morphData > 0 && morphDataArray != null && i < morphDataArray.GetLength(0) && currentFrame < morphDataArray.GetLength(1)) { AnimMorphData morphData = morphDataArray[i, currentFrame]; if (morphData != null && morphData.morphProgress != 0 && morphData.morphProgress != 100) { PhysicalObject morphToPO = perso.Perso3dData.ObjectList.entries[morphData.objectIndexTo].po; Vector3[] morphVerts = null; for (int j = 0; j < physicalObject.visualSet.Length; j++) { IGeometricObject obj = physicalObject.visualSet[j].obj; if (obj == null || obj as MeshObject == null) { continue; } MeshObject fromM = obj as MeshObject; MeshObject toM = morphToPO.visualSet[j].obj as MeshObject; if (toM == null) { continue; } if (fromM.vertices.Length != toM.vertices.Length) { // For those special cases like the mistake in the Clark cinematic continue; } int numVertices = fromM.vertices.Length; morphVerts = new Vector3[numVertices]; for (int vi = 0; vi < numVertices; vi++) { morphVerts[vi] = Vector3.Lerp(fromM.vertices[vi], toM.vertices[vi], morphData.morphProgressFloat); } for (int k = 0; k < fromM.num_subblocks; k++) { if (fromM.subblocks[k] == null || fromM.subblock_types[k] != 1) { continue; } MeshElement el = (MeshElement)fromM.subblocks[k]; if (el != null) { el.UpdateMeshVertices(morphVerts); } } } } else if (morphData != null && morphData.morphProgress == 100) { physicalObject.Gao.SetActive(false); PhysicalObject c = fullMorphPOs[i][morphData.objectIndexTo]; c.Gao.transform.localScale = c.scaleMultiplier.HasValue ? c.scaleMultiplier.Value : Vector3.one; c.Gao.transform.localPosition = Vector3.zero; c.Gao.transform.localRotation = Quaternion.identity; c.Gao.SetActive(true); currentActivePO[i] = -2; } else { for (int j = 0; j < physicalObject.visualSet.Length; j++) { IGeometricObject obj = physicalObject.visualSet[j].obj; if (obj == null || obj as MeshObject == null) { continue; } MeshObject fromM = obj as MeshObject; for (int k = 0; k < fromM.num_subblocks; k++) { if (fromM.subblocks[k] == null || fromM.subblock_types[k] != 1) { continue; } MeshElement el = (MeshElement)fromM.subblocks[k]; if (el != null) { el.ResetVertices(); } } } } } } if (hasBones) { for (int i = 0; i < a3d.num_channels; i++) { AnimChannel ch = a3d.channels[a3d.start_channels + i]; Transform baseChannelTransform = channelObjects[i].transform; Vector3 invertedScale = new Vector3(1f / baseChannelTransform.localScale.x, 1f / baseChannelTransform.localScale.y, 1f / baseChannelTransform.localScale.z); AnimNumOfNTTO numOfNTTO = a3d.numOfNTTO[ch.numOfNTTO + of.numOfNTTO]; AnimNTTO ntto = a3d.ntto[numOfNTTO.numOfNTTO]; PhysicalObject physicalObject = subObjects[i][numOfNTTO.numOfNTTO - a3d.start_NTTO]; if (physicalObject == null) { continue; } DeformSet bones = physicalObject.Bones; // Deformations if (bones != null) { for (int j = 0; j < a3d.num_deformations; j++) { AnimDeformation d = a3d.deformations[a3d.start_deformations + j]; if (d.channel < ch.id) { continue; } if (d.channel > ch.id) { break; } if (!channelIDDictionary.ContainsKey(d.linkChannel)) { continue; } List <int> ind_linkChannel_list = GetChannelByID(d.linkChannel); foreach (int ind_linkChannel in ind_linkChannel_list) { AnimChannel ch_link = a3d.channels[a3d.start_channels + ind_linkChannel]; AnimNumOfNTTO numOfNTTO_link = a3d.numOfNTTO[ch_link.numOfNTTO + of.numOfNTTO]; AnimNTTO ntto_link = a3d.ntto[numOfNTTO_link.numOfNTTO]; PhysicalObject physicalObject_link = subObjects[ind_linkChannel][numOfNTTO_link.numOfNTTO - a3d.start_NTTO]; if (physicalObject_link == null) { continue; } if (bones == null || bones.bones.Length <= d.bone + 1) { continue; } DeformBone bone = bones.r3bones[d.bone + 1]; if (bone != null) { Transform channelTransform = channelObjects[ind_linkChannel].transform; bone.UnityBone.transform.SetParent(channelTransform); bone.UnityBone.localPosition = Vector3.zero; bone.UnityBone.localRotation = Quaternion.identity; bone.UnityBone.localScale = Vector3.one; /*bone.UnityBone.position = channelTransform.position; * bone.UnityBone.rotation = channelTransform.rotation; * //bone.UnityBone.localScale = Vector3.one; * bone.UnityBone.localScale = channelTransform.localScale;*/ } } } } } } //this.currentFrame = (currentFrame + 1) % a3d.num_onlyFrames; } }
/// <summary> /// Calculate interpolation weights for the point (x,y) inside the <see cref="MeshElement"/>"/> /// <para> /// The weights returned can be used to calculate a value v at the point (x,y) using the /// <code>GetValue</code> methods /// </para> /// <para> /// if the point (x,y) is not inside the element, results are undefined. /// </para> /// </summary> /// <returns>Interpolation weights</returns> public static Weights InterpolationWeights(double x, double y, MeshElement element) { Weights weights = new Weights(); // Setting "out-of-bounds" index weights.Element1Index = -1; bool found = false; weights.Element1Index = element.Index; // Check which face the point belongs to, and which "side" of the face bool isQuad = element.IsQuadrilateral(); int numFaces = isQuad ? 4 : 3; for (int j = 0; j < numFaces; j++) { MeshFace elementFace = element.Faces[j]; // From the element (x,y), looking towards the face, // figure out wich node is right and which is left. MeshNode rightNode, leftNode; if (elementFace.LeftElement == element) { rightNode = elementFace.FromNode; leftNode = elementFace.ToNode; } else { rightNode = elementFace.ToNode; leftNode = elementFace.FromNode; } double elementXCenter = element.XCenter; double elementYCenter = element.YCenter; double rightNodeX = rightNode.X; double rightNodeY = rightNode.Y; double leftNodeX = leftNode.X; double leftNodeY = leftNode.Y; // Find also the element on the other side of the face double otherElementX, otherElementY; MeshElement otherElement = elementFace.OtherElement(element); if (otherElement != null) { otherElementX = otherElement.XCenter; otherElementY = otherElement.YCenter; weights.Element2Index = otherElement.Index; } else { // No other element - boundary face, use center of face. otherElementX = 0.5 * (rightNodeX + leftNodeX); otherElementY = 0.5 * (rightNodeY + leftNodeY); // Use "itself" as element-2 weights.Element2Index = element.Index; } // Check if point is on the right side of the line between element and other-element if (MeshExtensions.IsPointInsideLines(x, y, elementXCenter, elementYCenter, rightNodeX, rightNodeY, otherElementX, otherElementY)) { (double w1, double w2, double w3) = MeshExtensions.InterpolationWeights( x, y, elementXCenter, elementYCenter, rightNodeX, rightNodeY, otherElementX, otherElementY); weights.NodeIndex = rightNode.Index; weights.Element1Weight = w1; weights.NodeWeight = w2; weights.Element2Weight = w3; found = true; break; } // Check if point is on the left side of the line between element and other-element if (MeshExtensions.IsPointInsideLines(x, y, elementXCenter, elementYCenter, otherElementX, otherElementY, leftNodeX, leftNodeY)) { (double w1, double w2, double w3) = MeshExtensions.InterpolationWeights( x, y, elementXCenter, elementYCenter, otherElementX, otherElementY, leftNodeX, leftNodeY); weights.NodeIndex = leftNode.Index; weights.Element1Weight = w1; weights.Element2Weight = w2; weights.NodeWeight = w3; found = true; break; } } if (!found) // Should never happen, but just in case { weights.Element1Weight = 1; weights.Element2Weight = 0; weights.NodeWeight = 0; weights.Element2Index = element.Index; weights.NodeIndex = element.Nodes[0].Index; } return(weights); }
public static Mesh CombineEx(MeshInstance[] combines, bool generateStrips, ref MeshElement element) { int vertexCount = 0; int triangleCount = 0; int stripCount = 0; for (int i = 0; i < combines.Length; i++) { if (combines[i].mesh != null) { vertexCount += combines[i].mesh.vertexCount; if (generateStrips) { // SUBOPTIMAL FOR PERFORMANCE int curStripCount = combines[i].mesh.GetTriangles(combines[i].subMeshIndex).Length; if (curStripCount != 0) { if (stripCount != 0) { if ((stripCount & 1) == 1) stripCount += 3; else stripCount += 2; } stripCount += curStripCount; } else { generateStrips = false; } } } } // Precomputed how many triangles we need instead //在save时,这些数据全部不需要改变,要改变的只有顶点的位置. if (!generateStrips) { for (int i = 0; i < combines.Length; i++) { if (combines[i].mesh != null) { triangleCount += combines[i].mesh.GetTriangles(combines[i].subMeshIndex).Length; } } } Vector3[] vertices = element.vertices; Vector3[] normals = element.normals; Vector4[] tangents = element.tangents; Vector2[] uv = element.uv; Vector2[] uv1 = element.uv1; Color[] colors = element.colors; int[] triangles = element.triangles; int[] strip = element.strip; int offset; offset = 0; for (int i = 0; i < combines.Length; i++) { if (combines[i].mesh != null) Copy(combines[i].mesh.vertexCount, combines[i].mesh.vertices, vertices, ref offset, combines[i].transform); } //offset = 0; //for (int i = 0; i < combines.Length; i++) //{ // if (combines[i].mesh != null) // { // Matrix4x4 invTranspose = combines[i].transform; // invTranspose = invTranspose.inverse.transpose; // CopyNormal(combines[i].mesh.vertexCount, combines[i].mesh.normals, normals, ref offset, invTranspose); // } //} //offset = 0; //for (int i = 0; i < combines.Length; i++) //{ // if (combines[i].mesh != null) // { // Matrix4x4 invTranspose = combines[i].transform; // invTranspose = invTranspose.inverse.transpose; // CopyTangents(combines[i].mesh.vertexCount, combines[i].mesh.tangents, tangents, ref offset, invTranspose); // } //} //offset = 0; //for (int i = 0; i < combines.Length; i++) //{ // if (combines[i].mesh != null) // Copy(combines[i].mesh.vertexCount, combines[i].mesh.uv, uv, ref offset); //} //offset = 0; //for (int i = 0; i < combines.Length; i++) //{ // if (combines[i].mesh) // Copy(combines[i].mesh.vertexCount, combines[i].mesh.uv2, uv1, ref offset); //} //offset = 0; //for (int i = 0; i < combines.Length; i++) //{ // if (combines[i].mesh) // CopyColors(combines[i].mesh.vertexCount, combines[i].mesh.colors, colors, ref offset); //} //int triangleOffset = 0; //int stripOffset = 0; //int vertexOffset = 0; //for (int i = 0; i < combines.Length; i++) //{ // if (combines[i].mesh) // { // if (generateStrips) // { // int[] inputstrip = combines[i].mesh.GetTriangles(combines[i].subMeshIndex); // if (stripOffset != 0) // { // if ((stripOffset & 1) == 1) // { // strip[stripOffset + 0] = strip[stripOffset - 1]; // strip[stripOffset + 1] = inputstrip[0] + vertexOffset; // strip[stripOffset + 2] = inputstrip[0] + vertexOffset; // stripOffset += 3; // } // else // { // strip[stripOffset + 0] = strip[stripOffset - 1]; // strip[stripOffset + 1] = inputstrip[0] + vertexOffset; // stripOffset += 2; // } // } // for (int j = 0; j < inputstrip.Length; j++) // { // strip[j + stripOffset] = inputstrip[j] + vertexOffset; // } // stripOffset += inputstrip.Length; // } // else // { // int[] inputtriangles = combines[i].mesh.GetTriangles(combines[i].subMeshIndex); // for (int j = 0; j < inputtriangles.Length; j++) // { // triangles[j + triangleOffset] = inputtriangles[j] + vertexOffset; // } // triangleOffset += inputtriangles.Length; // } // vertexOffset += combines[i].mesh.vertexCount; // } //} Mesh mesh = element.mesh; mesh.vertices = vertices; //mesh.normals = normals; //mesh.colors = colors; //mesh.uv = uv; //mesh.uv2 = uv1; //mesh.tangents = tangents; //if (generateStrips) // mesh.SetTriangles(strip, 0); //else // mesh.triangles = triangles; return mesh; }
public void InterpolationTest(string sourceMeshFileName, string targetMeshFileName, CircularValueTypes cvt = CircularValueTypes.Normal) { // Source mesh MeshFile meshFile = MeshFile.ReadMesh(sourceMeshFileName); MeshData mesh = meshFile.ToMeshData(); mesh.BuildDerivedData(); // Mesh to interpolate to MeshFile targetFile = MeshFile.ReadMesh(targetMeshFileName); MeshData targetmesh = targetFile.ToMeshData(); // Setup interpolator MeshInterpolator2D interpolator = new MeshInterpolator2D(mesh) { CircularType = cvt, AllowExtrapolation = true }; interpolator.SetupNodeInterpolation(); interpolator.SetTarget(targetmesh); // Find reference x and y value as the smallest x and y value double xMin = mesh.Nodes.Select(mn => mn.X).Min(); double xMax = mesh.Nodes.Select(mn => mn.X).Max(); double yMin = mesh.Nodes.Select(mn => mn.Y).Min(); double yMax = mesh.Nodes.Select(mn => mn.Y).Max(); // Function over the (x,y) plane. Func <double, double, double> function = ValueFunction(cvt, xMin, yMin, xMax, yMax); // Calculate element center values of function double[] elmtVals = new double[mesh.Elements.Count]; for (int i = 0; i < mesh.Elements.Count; i++) { MeshElement elmt = mesh.Elements[i]; elmtVals[i] = function(elmt.XCenter, elmt.YCenter); } // Write out bounds, to check we got things right Console.Out.WriteLine("{0,10} (min,max) = ({1},{2})", cvt, elmtVals.Min(), elmtVals.Max()); // Interpolate to nodes double[] targetValues = new double[targetmesh.Elements.Count]; interpolator.InterpolateToTarget(elmtVals, targetValues); // Check node values for (int i = 0; i < targetmesh.Elements.Count; i++) { MeshElement targetElmt = targetmesh.Elements[i]; double exactValue = function(targetElmt.XCenter, targetElmt.YCenter); double interpValue = targetValues[i]; double diff = exactValue - interpValue; // Check if target element has a boundary node. // Nodes on the boundary may not have correctly interpolated value due to // inverse distance interpolation on the boundary, and hence also interpolation // to target element value will not be exact. So only check on those elements that are // fully internal (no boundary nodes). bool internalElmt = targetElmt.Nodes.Select(node => node.Code).All(code => code == 0); if (internalElmt && diff > 1e-6 * Math.Max(Math.Abs(exactValue), 1)) { string msg = string.Format("{0,2} : {1}-{2}={3} ({4},{5})", i, exactValue, interpValue, diff, targetElmt.XCenter, targetElmt.YCenter); Console.Out.WriteLine(msg); Assert.Fail(msg); } } }