public AddTube ( IList |
||
path | IList |
/// A list of points defining the centers of the tube. /// |
values | IList |
/// The texture coordinate X values (optional). /// |
diameters | IList |
/// The diameters (optional). /// |
section | IList |
/// The section to extrude along the tube path. /// |
isTubeClosed | bool |
/// If the tube is closed set to |
isSectionClosed | bool |
/// if set to |
return | void |
/// <summary> /// Do the tessellation and return the <see cref="MeshGeometry3D"/> . /// </summary> /// <returns> /// A triangular mesh geometry. /// </returns> protected override MeshGeometry3D Tessellate() { if (this.Path == null || this.Path.Count < 2) { return null; } // See also "The GLE Tubing and Extrusion Library": // http://linas.org/gle/ // http://sharpmap.codeplex.com/Thread/View.aspx?ThreadId=18864 var builder = new MeshBuilder(false, this.TextureCoordinates != null); var sectionXAxis = this.SectionXAxis; if (sectionXAxis.Length < 1e-6) { sectionXAxis = new Vector3D(1, 0, 0); } var forward = this.Path[1] - this.Path[0]; var up = Vector3D.CrossProduct(forward, sectionXAxis); if (up.LengthSquared < 1e-6) { sectionXAxis = forward.FindAnyPerpendicular(); } builder.AddTube( this.Path, this.Angles, this.TextureCoordinates, this.Diameters, this.Section, sectionXAxis, this.IsPathClosed, this.IsSectionClosed); // Add Caps if wanted and needed if (this.AddCaps && !this.IsPathClosed && builder.Positions.Count >= Section.Count) { var sCount = Section.Count; var normals = new Vector3D[sCount]; var vertices = new Point3D[sCount]; var pCount = Path.Count; //Add back cap var circleBack = builder.Positions.Skip(builder.Positions.Count - sCount).Take(sCount).ToArray(); var normal = Path[pCount - 1] - Path[pCount - 2]; normal.Normalize(); for (int i = 0; i < normals.Length; ++i) { normals[i] = normal; } builder.AddTriangleFan(circleBack, normals); //Add front cap var circleFront = builder.Positions.Take(sCount).ToArray(); normal = Path[0] - Path[1]; normal.Normalize(); for (int i = 0; i < normals.Length; ++i) { normals[i] = normal; } builder.AddTriangleFan(circleFront, normals); } return builder.ToMesh(); }
private void CreateModel() { const double dt = 0.1; const int nSteps = 100; var mb = new MeshBuilder(true, true); for (double y0 = -5; y0 <= 5; y0 += 0.25) { var p0 = new Point(-3, y0); Point[] pts = Solve(Velocity, p0, dt, nSteps); var vel = new double[pts.Length]; var diam = new double[pts.Length]; int i = 0; var pts3d = new Point3D[pts.Length]; double vmax = 0; foreach (Point pt in pts) { pts3d[i] = new Point3D(pt.X, pt.Y, 0); double v = Velocity(pt.X, pt.Y).Length; if (v > vmax) vmax = v; vel[i++] = v; } for (int j = 0; j < vel.Length; j++) vel[j] /= vmax; for (int j = 0; j < vel.Length; j++) diam[j] = 0.075; mb.AddTube(pts3d, vel, diam, 12, false); } this.StreamLinesModel = new GeometryModel3D(); this.StreamLinesModel.Geometry = mb.ToMesh(); this.StreamLinesModel.Material = Materials.Hue; this.StreamLinesModel.BackMaterial = Materials.Hue; }
void AddTube(List<Point3D> path, Color color) { var mb = new MeshBuilder(); mb.AddTube(path, 0.1, 3, false); var geom = new GeometryModel3D { Geometry = mb.ToMesh(true), Material = MaterialHelper.CreateMaterial(color) }; // create a model var model = new ModelVisual3D(); model.Content = geom; _Helix.Children.Add(model); }
public TubeSegment(Point3D startPoint, Point3D endPoint, double d1, double d2) { var meshBuilder = new MeshBuilder(false, false); var h1 = 0.1*d1; var h2 = 0.1*d2; var deltaStart = GeometryHelper.GetDeltaPoint(startPoint, endPoint, h1); var deltaEnd = GeometryHelper.GetDeltaPoint(endPoint, startPoint, h2); var points = new List<Point3D>() { deltaStart, deltaEnd }; //var points = new List<Point3D>() { startPoint, endPoint }; var dd1 = d1*0.9; var dd2 = d2*0.9; var diameters = new[] { dd1, dd2 }; //var diameters = new[] { d1, d2 }; meshBuilder.AddTube(points, new double[] { 0, 0 }, diameters, 10, false); Model = meshBuilder.ToMesh(); }
/// <summary> /// Place a tube down the center of the plot /// so all the arrows will connect to a center point (origin). /// </summary> /// <param name="numBins">Number of bins in the plot.</param> /// <returns>3D model of the center tube.</returns> private GeometryModel3D CreateOriginTube(int numBins) { double tubeDia = ARROW_HEAD_SIZE; // Tube Diameter. Same as Arrows. Min = 0.1 Max = 1.0 int tubeTheta = 30; // Tube ThetaDiv. Min = 3 Max = 100 double xAxisLoc = 0; double yAxisLoc = 0; double zAxisLoc = 0; if (YAxis) { yAxisLoc = -numBins * TRANSLATION_SCALE; } else { xAxisLoc = numBins * TRANSLATION_SCALE; } // Create 2 points, the top and bottom List<Point3D> pts = new List<Point3D>(); pts.Add(new Point3D(0, 0, 0)); pts.Add(new Point3D(xAxisLoc, yAxisLoc, zAxisLoc)); // Create the tube based off the points var mb = new MeshBuilder(false, false); mb.AddTube(pts, tubeDia, tubeTheta, true); Geometry3D geometry = mb.ToMesh(); // Set the color Material material = MaterialHelper.CreateMaterial(Color.FromArgb(255, 255,250,213)); material.Freeze(); var model = new GeometryModel3D(geometry, material); return model; }
private Model3D CreateModel() { var plotModel = new Model3DGroup(); int rows = Points.GetUpperBound(0) + 1; int columns = Points.GetUpperBound(1) + 1; double minX = double.MaxValue; double maxX = double.MinValue; double minY = double.MaxValue; double maxY = double.MinValue; double minZ = double.MaxValue; double maxZ = double.MinValue; double minColorValue = double.MaxValue; double maxColorValue = double.MinValue; for (int i = 0; i < rows; i++) for (int j = 0; j < columns; j++) { double x = Points[i, j].X; double y = Points[i, j].Y; double z = Points[i, j].Z; maxX = Math.Max(maxX, x); maxY = Math.Max(maxY, y); maxZ = Math.Max(maxZ, z); minX = Math.Min(minX, x); minY = Math.Min(minY, y); minZ = Math.Min(minZ, z); if (ColorValues != null) { maxColorValue = Math.Max(maxColorValue, ColorValues[i, j]); minColorValue = Math.Min(minColorValue, ColorValues[i, j]); } } // make color value 0 at texture coordinate 0.5 if (Math.Abs(minColorValue) < Math.Abs(maxColorValue)) minColorValue = -maxColorValue; else maxColorValue = -minColorValue; // set the texture coordinates by z-value or ColorValue var texcoords = new Point[rows,columns]; for (int i = 0; i < rows; i++) for (int j = 0; j < columns; j++) { double u = (Points[i, j].Z - minZ)/(maxZ - minZ); if (ColorValues != null) u = (ColorValues[i, j] - minColorValue)/(maxColorValue - minColorValue); texcoords[i, j] = new Point(u, u); } var surfaceMeshBuilder = new MeshBuilder(); surfaceMeshBuilder.AddRectangularMesh(Points, texcoords); var surfaceModel = new GeometryModel3D(surfaceMeshBuilder.ToMesh(), MaterialHelper.CreateMaterial(SurfaceBrush, null, null, 1, 0)); surfaceModel.BackMaterial = surfaceModel.Material; var axesMeshBuilder = new MeshBuilder(); for (double x = minX; x <= maxX; x += IntervalX) { double j = (x - minX)/(maxX - minX)*(columns - 1); var path = new List<Point3D> {new Point3D(x, minY, minZ)}; for (int i = 0; i < rows; i++) { path.Add(BilinearInterpolation(Points, i, j)); } path.Add(new Point3D(x, maxY, minZ)); axesMeshBuilder.AddTube(path, LineThickness, 9, false); GeometryModel3D label = TextCreator.CreateTextLabelModel3D(x.ToString(), Brushes.Black, true, FontSize, new Point3D(x, minY - FontSize*2.5, minZ), new Vector3D(1, 0, 0), new Vector3D(0, 1, 0)); plotModel.Children.Add(label); } { GeometryModel3D label = TextCreator.CreateTextLabelModel3D("X-axis", Brushes.Black, true, FontSize, new Point3D((minX + maxX)*0.5, minY - FontSize*6, minZ), new Vector3D(1, 0, 0), new Vector3D(0, 1, 0)); plotModel.Children.Add(label); } for (double y = minY; y <= maxY; y += IntervalY) { double i = (y - minY)/(maxY - minY)*(rows - 1); var path = new List<Point3D> {new Point3D(minX, y, minZ)}; for (int j = 0; j < columns; j++) { path.Add(BilinearInterpolation(Points, i, j)); } path.Add(new Point3D(maxX, y, minZ)); axesMeshBuilder.AddTube(path, LineThickness, 9, false); GeometryModel3D label = TextCreator.CreateTextLabelModel3D(y.ToString(), Brushes.Black, true, FontSize, new Point3D(minX - FontSize*3, y, minZ), new Vector3D(1, 0, 0), new Vector3D(0, 1, 0)); plotModel.Children.Add(label); } { GeometryModel3D label = TextCreator.CreateTextLabelModel3D("Y-axis", Brushes.Black, true, FontSize, new Point3D(minX - FontSize*10, (minY + maxY)*0.5, minZ), new Vector3D(0, 1, 0), new Vector3D(-1, 0, 0)); plotModel.Children.Add(label); } double z0 = (int) (minZ/IntervalZ)*IntervalZ; for (double z = z0; z <= maxZ + double.Epsilon; z += IntervalZ) { GeometryModel3D label = TextCreator.CreateTextLabelModel3D(z.ToString(), Brushes.Black, true, FontSize, new Point3D(minX - FontSize*3, maxY, z), new Vector3D(1, 0, 0), new Vector3D(0, 0, 1)); plotModel.Children.Add(label); } { GeometryModel3D label = TextCreator.CreateTextLabelModel3D("Z-axis", Brushes.Black, true, FontSize, new Point3D(minX - FontSize*10, maxY, (minZ + maxZ)*0.5), new Vector3D(0, 0, 1), new Vector3D(1, 0, 0)); plotModel.Children.Add(label); } var bb = new Rect3D(minX, minY, minZ, maxX - minX, maxY - minY, 0*(maxZ - minZ)); axesMeshBuilder.AddBoundingBox(bb, LineThickness); var axesModel = new GeometryModel3D(axesMeshBuilder.ToMesh(), Materials.Black); plotModel.Children.Add(surfaceModel); plotModel.Children.Add(axesModel); return plotModel; }
private static void BuildRailing( MeshBuilder railingBuilder, List<Point3D> bases, double height, double diameter, int railings) { foreach (var point in bases) { railingBuilder.AddCylinder(point, point + new Vector3D(0, 0, height), diameter, 10); } for (int i = 1; i <= railings; i++) { var h = height * i / railings; var path = bases.Select(p => p + new Vector3D(0, 0, h)).ToArray(); railingBuilder.AddTube(path, diameter, 10, false); } }
/// <summary> /// Creates a rather ugly visual representatino of the polyline. /// Fixed in size with respect to the model. /// </summary> /// <param name="highlighted">The destination visual component to replace the content of.</param> internal void SetToVisual(MeshVisual3D highlighted) { if (_geomPoints == null) return; var lines = new LinesVisual3D { Color = Colors.Yellow }; var axesMeshBuilder = new MeshBuilder(); List<Point3D> path = new List<Point3D>(); foreach (var item in _geomPoints) { axesMeshBuilder.AddSphere(item.Point, 0.1); path.Add(item.Point); } if (_geomPoints.Count > 1) { double lineThickness = 0.05; axesMeshBuilder.AddTube(path, lineThickness, 9, false); } highlighted.Content = new GeometryModel3D(axesMeshBuilder.ToMesh(), Materials.Yellow); }
private void AppearanceChanged() { var builder = new MeshBuilder(false, true); // hard code a kerb section var section = new PointCollection(); int m = 41; double n = 4; double a = this.Width / 2; double b = this.Height; for (int i = 0; i < m; i++) { double t = Math.PI * i / (m - 1); section.Add(new Point( a * Math.Sign(Math.Cos(t)) * Math.Pow(Math.Abs(Math.Cos(t)), 2 / n), -b * Math.Sign(Math.Sin(t)) * Math.Pow(Math.Abs(Math.Sin(t)), 2 / n))); } // calculate the texture coordinates var values = new List<double> { 0 }; for (int i = 1; i < this.Positions.Count; i++) { var d = this.Positions[i - 1].DistanceTo(this.Positions[i]); values.Add(values[values.Count - 1] + (d / this.Length)); } // create the extruded geometry builder.AddTube(this.Positions, null, values, null, section, new Vector3D(1, 0, 0), false, false); this.kerbModel.Geometry = builder.ToMesh(); }
private Model3D CreateModel() { if (Points == null || Points.Length == 0) return null; var plotModel = new Model3DGroup(); int rows = Points.GetUpperBound(0) + 1; int columns = Points.GetUpperBound(1) + 1; double minX = double.MaxValue; double maxX = double.MinValue; double minY = double.MaxValue; double maxY = double.MinValue; double minZ = double.MaxValue; double maxZ = double.MinValue; double minColorValue = double.MaxValue; double maxColorValue = double.MinValue; minX = Points.OfType<Point3D>().Min(x => x.X); maxX = Points.OfType<Point3D>().Max(x => x.X); minY = Points.OfType<Point3D>().Min(x => x.Y); maxY = Points.OfType<Point3D>().Max(x => x.Y); minZ = Points.OfType<Point3D>().Min(x => x.Z); maxZ = Points.OfType<Point3D>().Max(x => x.Z); if (ColorValues != null) minColorValue = ColorValues.OfType<double>().Min(x => x); if (ColorValues != null) maxColorValue = ColorValues.OfType<double>().Max(x => x); if (Functions.Abs(minColorValue) < Functions.Abs(maxColorValue)) minColorValue = -maxColorValue; else maxColorValue = -minColorValue; BitmapPixelMaker bm_maker = new BitmapPixelMaker(columns, rows); for (int ix = 0; ix < columns; ix++) { for (int iy = 0; iy < rows; iy++) { try { byte red, green, blue; MapRainbowColor(Points[ix, iy].Z, minZ, maxZ, out red, out green, out blue); bm_maker.SetPixel(ix, iy, red, green, blue, 255); } catch { } } } var texcoords = new Point[rows, columns]; for (int i = 0; i < rows; i++) for (int j = 0; j < columns; j++) { texcoords[i, j] = new Point(i, j); } var surfaceMeshBuilder = new MeshBuilder(); surfaceMeshBuilder.AddRectangularMesh(Points, texcoords); var surfaceModel = new GeometryModel3D(surfaceMeshBuilder.ToMesh(), MaterialHelper.CreateMaterial(new ImageBrush(bm_maker.MakeBitmap(128, 128)), null, null, 1, 0)); surfaceModel.BackMaterial = surfaceModel.Material; var axesMeshBuilder = new MeshBuilder(); for (double x = minX; x <= maxX; x += IntervalX) { double j = (x - minX) / (maxX - minX) * (columns - 1); var path = new List<Point3D> {new Point3D(x, minY, minZ)}; for (int i = 0; i < rows; i++) { path.Add(BilinearInterpolation(Points, i, j)); } path.Add(new Point3D(x, maxY, minZ)); axesMeshBuilder.AddTube(path, LineThickness, 9, false); GeometryModel3D label = TextCreator.CreateTextLabelModel3D(x.ToString(), Brushes.Black, true, FontSize * 3, new Point3D(x, minY - FontSize * 2.5, minZ), new Vector3D(1, 0, 0), new Vector3D(0, 1, 0)); plotModel.Children.Add(label); } { GeometryModel3D label = TextCreator.CreateTextLabelModel3D("Axe réel", Brushes.Black, true, FontSize * 10, new Point3D((minX + maxX) * 0.25, minY - FontSize * 6 - 0.5, minZ), new Vector3D(1, 0, 0), new Vector3D(0, 1, 0)); plotModel.Children.Add(label); } for (double y = minY; y <= maxY; y += IntervalY) { double i = (y - minY) / (maxY - minY) * (rows - 1); var path = new List<Point3D> {new Point3D(minX, y, minZ)}; for (int j = 0; j < columns; j++) { path.Add(BilinearInterpolation(Points, i, j)); } path.Add(new Point3D(maxX, y, minZ)); axesMeshBuilder.AddTube(path, LineThickness, 9, false); GeometryModel3D label = TextCreator.CreateTextLabelModel3D(y.ToString(), Brushes.Black, true, FontSize * 3, new Point3D(minX - FontSize * 3, y, minZ), new Vector3D(0, 1, 0), new Vector3D(1, 0, 0)); plotModel.Children.Add(label); } { GeometryModel3D label = TextCreator.CreateTextLabelModel3D("Axe imaginaire", Brushes.Black, true, FontSize * 10, new Point3D(minX - FontSize * 10, (minY + maxY) * 0.5, minZ), new Vector3D(0, 1, 0), new Vector3D(1, 0, 0)); plotModel.Children.Add(label); } double z0 = (int) (minZ / IntervalZ) * IntervalZ; for (double z = z0; z <= maxZ + double.Epsilon; z += IntervalZ) { GeometryModel3D label = TextCreator.CreateTextLabelModel3D(z.ToString(), Brushes.Black, true, FontSize * 3, new Point3D(minX - FontSize * 3, maxY, z), new Vector3D(1, 0, 0), new Vector3D(0, 0, 1)); plotModel.Children.Add(label); } { GeometryModel3D label = TextCreator.CreateTextLabelModel3D("Module", Brushes.Black, true, FontSize * 10, new Point3D(minX - FontSize * 10 - 1.5, maxY, (minZ + maxZ) * 0.5), new Vector3D(1, 0, 0), new Vector3D(0, 0, 1)); plotModel.Children.Add(label); } var bb = new Rect3D(minX, minY, minZ, maxX - minX, maxY - minY, (maxZ - minZ)); axesMeshBuilder.AddBoundingBox(bb, LineThickness); var axesModel = new GeometryModel3D(axesMeshBuilder.ToMesh(), Materials.Black); plotModel.Children.Add(surfaceModel); plotModel.Children.Add(axesModel); return plotModel; }
/// <summary> /// This function contains all the "business logic" for constructing a SurfacePlot 3D. /// </summary> /// <returns>A Model3DGroup containing all the component models (mesh, surface definition, grid objects, etc).</returns> private Model3DGroup CreateModel() { var newModelGroup = new Model3DGroup(); double lineThickness = 0.01; double axesOffset = 0.05; // Get relevant constaints from the DataPoints object int numberOfRows = DataPoints.GetUpperBound(0) + 1; int numberOfColumns = DataPoints.GetUpperBound(1) + 1; // Determine the x, y, and z ranges of the DataPoints collection double minX = double.MaxValue; double maxX = double.MinValue; double minY = double.MaxValue; double maxY = double.MinValue; double minZ = double.MaxValue; double maxZ = double.MinValue; double minColorValue = double.MaxValue; double maxColorValue = double.MinValue; for (int i = 0; i < numberOfRows; i++) { for (int j = 0; j < numberOfColumns; j++) { double x = DataPoints[i, j].X; double y = DataPoints[i, j].Y; double z = DataPoints[i, j].Z; maxX = Math.Max(maxX, x); maxY = Math.Max(maxY, y); maxZ = Math.Max(maxZ, z); minX = Math.Min(minX, x); minY = Math.Min(minY, y); minZ = Math.Min(minZ, z); if (ColorValues != null) { maxColorValue = Math.Max(maxColorValue, ColorValues[i, j]); minColorValue = Math.Min(minColorValue, ColorValues[i, j]); } } } /* TEMP */ int numberOfXAxisTicks = 10; int numberOfYAxisTicks = 10; int numberOfZAxisTicks = 5; double XAxisInterval = (maxX - minX) / numberOfXAxisTicks; double YAxisInterval = (maxY - minY) / numberOfYAxisTicks; double ZAxisInterval = (maxZ - minZ) / numberOfZAxisTicks; /* /TEMP */ // Set color value to 0 at texture coordinate 0.5, with an even spread in either direction if (Math.Abs(minColorValue) < Math.Abs(maxColorValue)) { minColorValue = -maxColorValue; } else { maxColorValue = -minColorValue; } // Set the texture coordinates by either z-value or ColorValue var textureCoordinates = new Point[numberOfRows, numberOfColumns]; for (int i = 0; i < numberOfRows; i++) { for (int j = 0; j < numberOfColumns; j++) { double tc; if (ColorValues != null) { tc = (ColorValues[i, j] - minColorValue) / (maxColorValue - minColorValue); } else { tc = (DataPoints[i, j].Z - minZ) / (maxZ - minZ); } textureCoordinates[i, j] = new Point(tc, tc); } } // Build the surface model (i.e. the coloured surface model) MeshBuilder surfaceModelBuilder = new MeshBuilder(); surfaceModelBuilder.AddRectangularMesh(DataPoints, textureCoordinates); GeometryModel3D surfaceModel = new GeometryModel3D(surfaceModelBuilder.ToMesh(), MaterialHelper.CreateMaterial(SurfaceBrush, null, null, 1, 0)); surfaceModel.BackMaterial = surfaceModel.Material; // Instantiate MeshBuilder objects for the Grid and SurfaceMeshLines meshes MeshBuilder surfaceMeshLinesBuilder = new MeshBuilder(); MeshBuilder surfaceContourLinesBuilder = new MeshBuilder(); MeshBuilder gridBuilder = new MeshBuilder(); // Build the axes labels model (i.e. the object that holds the axes labels and ticks) ModelVisual3D axesLabelsModel = new ModelVisual3D(); // Loop through x intervals - for the surface meshlines, the grid, and X axes ticks for (double x = minX; x <= maxX + 0.0001; x += XAxisInterval) { // Add surface mesh lines which denote intervals along the x-axis var surfacePath = new List<Point3D>(); double i = (x - minX) / (maxX - minX) * (numberOfColumns - 1); for (int j = 0; j < numberOfColumns; j++) { surfacePath.Add(DoBilinearInterpolation(DataPoints, i, j)); } surfaceMeshLinesBuilder.AddTube(surfacePath, lineThickness, 9, false); // Axes labels BillboardTextVisual3D label = new BillboardTextVisual3D(); label.Text = string.Format("{0:F2}", x); label.Position = new Point3D(x, minY - axesOffset, minZ - axesOffset); axesLabelsModel.Children.Add(label); // Grid lines var gridPath = new List<Point3D>(); gridPath.Add(new Point3D(x, minY, minZ)); gridPath.Add(new Point3D(x, maxY, minZ)); gridPath.Add(new Point3D(x, maxY, maxZ)); gridBuilder.AddTube(gridPath, lineThickness, 9, false); } // Loop through y intervals - for the surface meshlines, the grid, and Y axes ticks for (double y = minY; y <= maxY + 0.0001; y += YAxisInterval) { // Add surface mesh lines which denote intervals along the y-axis var path = new List<Point3D>(); double j = (y - minY) / (maxY - minY) * (numberOfRows - 1); for (int i = 0; i < numberOfRows; i++) { path.Add(DoBilinearInterpolation(DataPoints, i, j)); } surfaceMeshLinesBuilder.AddTube(path, lineThickness, 9, false); // Axes labels BillboardTextVisual3D label = new BillboardTextVisual3D(); label.Text = string.Format("{0:F2}", y); label.Position = new Point3D(minX - axesOffset, y, minZ - axesOffset); axesLabelsModel.Children.Add(label); // Grid lines var gridPath = new List<Point3D>(); gridPath.Add(new Point3D(minX, y, minZ)); gridPath.Add(new Point3D(maxX, y, minZ)); gridPath.Add(new Point3D(maxX, y, maxZ)); gridBuilder.AddTube(gridPath, lineThickness, 9, false); } // Loop through z intervals - for the grid, and Z axes ticks for (double z = minZ; z <= maxZ + 0.0001; z += ZAxisInterval) { // Grid lines var path = new List<Point3D>(); path.Add(new Point3D(minX, maxY, z)); path.Add(new Point3D(maxX, maxY, z)); path.Add(new Point3D(maxX, minY, z)); gridBuilder.AddTube(path, lineThickness, 9, false); // Axes labels BillboardTextVisual3D label = new BillboardTextVisual3D(); label.Text = string.Format("{0:F2}", z); label.Position = new Point3D(minX - axesOffset, maxY + axesOffset, z); axesLabelsModel.Children.Add(label); } // Add axes labels BillboardTextVisual3D xLabel = new BillboardTextVisual3D(); xLabel.Text = "X Axis"; xLabel.Position = new Point3D((maxX - minX) / 2, minY - 3 * axesOffset, minZ - 5 * axesOffset); axesLabelsModel.Children.Add(xLabel); BillboardTextVisual3D yLabel = new BillboardTextVisual3D(); yLabel.Text = "Y Axis"; yLabel.Position = new Point3D(minX - 3 * axesOffset, (maxY - minY) / 2, minZ - 5 * axesOffset); axesLabelsModel.Children.Add(yLabel); BillboardTextVisual3D zLabel = new BillboardTextVisual3D(); zLabel.Text = "Z Axis"; zLabel.Position = new Point3D(minX - 5 * axesOffset, maxY + 5 * axesOffset, 0); // Note: trying to find the midpoint of minZ, maxZ doesn't work when minZ = -0.5 and maxZ = 0.5... axesLabelsModel.Children.Add(zLabel); // Create models from MeshBuilders GeometryModel3D surfaceMeshLinesModel = new GeometryModel3D(surfaceMeshLinesBuilder.ToMesh(), Materials.Black); GeometryModel3D gridModel = new GeometryModel3D(gridBuilder.ToMesh(), Materials.Black); // Update model group //this.Children.Add(axesLabelsModel); newModelGroup.Children.Add(surfaceModel); newModelGroup.Children.Add(surfaceMeshLinesModel); newModelGroup.Children.Add(gridModel); //ScaleTransform3D surfaceTransform = new ScaleTransform3D(20, 20, 20, 0, 0, 0); //newModelGroup.Transform = surfaceTransform; return newModelGroup; }
/// <summary> /// The create solution geometry. /// </summary> /// <param name="solution">The solution.</param> /// <param name="height">The height.</param> /// <param name="diameter">The diameter.</param> /// <returns>The solution tube geometry.</returns> private MeshGeometry3D CreateSolutionGeometry(IEnumerable<Cell> solution, double height = 0.25, double diameter = 0.25) { var builder = new MeshBuilder(); var path = solution.Select(cell => this.GetPosition(cell, height)).ToList(); var spline = CanonicalSplineHelper.CreateSpline(path, 0.7, null, false, 0.05); builder.AddTube(spline, diameter, 13, false); return builder.ToMesh(); }
/// <summary> /// Do the tessellation and return the <see cref="MeshGeometry3D"/> . /// </summary> /// <returns> /// A triangular mesh geometry. /// </returns> protected override MeshGeometry3D Tessellate() { if (this.Path == null || this.Path.Count < 2) { return null; } // See also "The GLE Tubing and Extrusion Library": // http://linas.org/gle/ // http://sharpmap.codeplex.com/Thread/View.aspx?ThreadId=18864 var builder = new MeshBuilder(false, this.TextureCoordinates != null); var sectionXAxis = this.SectionXAxis; if (sectionXAxis.Length < 1e-6) { sectionXAxis = new Vector3D(1, 0, 0); } var forward = this.Path[1] - this.Path[0]; var up = Vector3D.CrossProduct(forward, sectionXAxis); if (up.LengthSquared < 1e-6) { sectionXAxis = forward.FindAnyPerpendicular(); } builder.AddTube( this.Path, this.Angles, this.TextureCoordinates, this.Diameters, this.Section, sectionXAxis, this.IsPathClosed, this.IsSectionClosed); return builder.ToMesh(); }
private void UpdateModel() { // http://en.wikipedia.org/wiki/Lorenz_attractor Func<double[], double[]> lorenzAttractor = x => { var dx = new double[3]; dx[0] = sigma * (x[1] - x[0]); dx[1] = x[0] * (rho - x[2]) - x[1]; dx[2] = x[0] * x[1] - beta * x[2]; return dx; }; // solve the ODE var x0 = new[] { 0, 1, 1.05 }; IEnumerable<double[]> solution = EulerSolver(lorenzAttractor, x0, 25); // todo: should have a better ODE solver (R-K(4,5)? http://www.mathworks.com/help/techdoc/ref/ode45.html) List<Point3D> path = solution.Select(x => new Point3D(x[0], x[1], x[2])).ToList(); // create the WPF3D model var m = new Model3DGroup(); var gm = new MeshBuilder(); gm.AddTube(path, 0.8, 10, false); if (directionArrows) { // sphere at the initial point gm.AddSphere(path[0], 1); // arrow heads every 100 point for (int i = 100; i + 1 < path.Count; i += 100) { gm.AddArrow(path[i], path[i + 1], 0.8); } // arrow head at the end Point3D p0 = path[path.Count - 2]; Point3D p1 = path[path.Count - 1]; var d = new Vector3D(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); d.Normalize(); Point3D p2 = p1 + d * 2; gm.AddArrow(p1, p2, 0.8); } m.Children.Add(new GeometryModel3D(gm.ToMesh(), Materials.Gold)); Model = m; }
private Model3D CreateModel() { // if (Points ==null) var plotModel = new Model3DGroup(); int rows = Points.GetUpperBound(0) + 1; int columns = Points.GetUpperBound(1) + 1; double minX = double.MaxValue; double maxX = double.MinValue; double minY = double.MaxValue; double maxY = double.MinValue; double minZ = double.MaxValue; double maxZ = double.MinValue; //double RealminX = double.MaxValue; //double RealmaxX = double.MinValue; //double RealminY = double.MaxValue; //double RealmaxY = double.MinValue; //double RealminZ = double.MaxValue; //double RealmaxZ = double.MinValue; #region Color things double minColorValue = double.MaxValue; double maxColorValue = double.MinValue; for (int i = 0; i < rows; i++) for (int j = 0; j < columns; j++) { double x = Points[i, j].X; double y = Points[i, j].Y; double z = Points[i, j].Z; maxX = Math.Max(maxX, x); maxY = Math.Max(maxY, y); maxZ = Math.Max(maxZ, z); minX = Math.Min(minX, x); minY = Math.Min(minY, y); minZ = Math.Min(minZ, z); if (ColorValues != null) { maxColorValue = Math.Max(maxColorValue, ColorValues[i, j]); minColorValue = Math.Min(minColorValue, ColorValues[i, j]); } } // make color value 0 at texture coordinate 0.5 if (Math.Abs(minColorValue) < Math.Abs(maxColorValue)) minColorValue = -maxColorValue; else maxColorValue = -minColorValue; #endregion // set the texture coordinates by z-value or ColorValue var texcoords = new Point[rows,columns]; if (OriginalData == null || ColorCoding != ComplexPlainVisualizer.ColorCoding.Custom) { for (int i = 0; i < rows; i++) for (int j = 0; j < columns; j++) { double u = (Points[i, j].Z - minZ) / (maxZ - minZ); //double v = if (ColorValues != null) u = (ColorValues[i, j] - minColorValue) / (maxColorValue - minColorValue); texcoords[i, j] = new Point(u, u); } } else { for (int i = 0; i < rows; i++) for (int j = 0; j < columns; j++) { double u = MathUtil.Scale(minZ, maxZ, Math.Log10(OriginalData[i, j].Z), 0.5); double v = OriginalData[i, j].W; double uu = 0.5 + u * Math.Cos(v); double vv = 0.5 + u * Math.Sin(v); texcoords[i, j] = new Point(uu, vv); } } if (AutoScale) { ScaleX =10 / Math.Abs(maxX - minX); ScaleY =10/ Math.Abs(maxY - minY); ScaleZ =5 / Math.Abs(maxZ - minZ); } var surfaceMeshBuilder = new MeshBuilder(); surfaceMeshBuilder.AddRectangularMesh(Points, texcoords); surfaceMeshBuilder.Scale(ScaleX, ScaleY, ScaleZ); var surfaceModel = new GeometryModel3D(surfaceMeshBuilder.ToMesh(), MaterialHelper.CreateMaterial(SurfaceBrush, null, null, 1, 0)); surfaceModel.BackMaterial = surfaceModel.Material; //RealmaxX = maxX; //RealminX = minX; //RealmaxY = maxY; //RealminY = minY; //RealmaxZ = maxZ; //RealminZ = minZ; maxX *= ScaleX; minX *= ScaleX; maxY *= ScaleY; minY *= ScaleY; maxZ *= ScaleZ; minZ *= ScaleZ; IntervalX = (maxX - minX) / SubAxisCount; IntervalY = (maxY - minY) / SubAxisCount; IntervalZ = (maxZ - minZ) / SubAxisCount; #region eje x var axesMeshBuilder = new MeshBuilder(); for (double x = minX; x <= maxX; x += IntervalX) { double j = (x - minX)/(maxX - minX)*(columns - 1); //var path = new List<Point3D> { new Point3D(x , minY , minZ) }; var path = new List<Point3D> { new Point3D(x, minY , minZ) }; for (int i = 0; i < rows; i++) { Point3D p = BilinearInterpolation(Points, i, j); p.X *= ScaleX; p.Y *= ScaleY; p.Z *= ScaleZ; path.Add(p); } path.Add(new Point3D(x, maxY, minZ)); axesMeshBuilder.AddTube(path, LineThickness, 9, false); GeometryModel3D label = TextCreator.CreateTextLabelModel3D(StringUtils.CodeString(x / ScaleX), Brushes.Black, true, FontSize, new Point3D(x, minY - FontSize * 2.5, minZ), new Vector3D(1, 0, 0), new Vector3D(0, 1, 0)); plotModel.Children.Add(label); } { GeometryModel3D label = TextCreator.CreateTextLabelModel3D("X-axis", Brushes.Black, true, FontSize, new Point3D((minX + maxX)*0.5, minY - FontSize * 6, minZ), new Vector3D(1, 0, 0), new Vector3D(0, 1, 0)); plotModel.Children.Add(label); } #endregion #region eje y for (double y = minY; y <= maxY; y += IntervalY) { double i = (y - minY)/(maxY - minY)*(rows - 1); var path = new List<Point3D> {new Point3D(minX, y, minZ)}; for (int j = 0; j < columns; j++) { Point3D p = BilinearInterpolation(Points, i, j); p.X *= ScaleX; p.Y *= ScaleY; p.Z *= ScaleZ; path.Add(p); } path.Add(new Point3D(maxX, y, minZ)); axesMeshBuilder.AddTube(path, LineThickness, 9, false); GeometryModel3D label = TextCreator.CreateTextLabelModel3D(StringUtils.CodeString(y / ScaleY), Brushes.Black, true, FontSize, new Point3D(minX - FontSize * 3, y, minZ), new Vector3D(1, 0, 0), new Vector3D(0, 1, 0)); plotModel.Children.Add(label); } { GeometryModel3D label = TextCreator.CreateTextLabelModel3D("Y-axis", Brushes.Black, true, FontSize, new Point3D(minX - FontSize * 10, (minY + maxY) * 0.5, minZ), new Vector3D(0, 1, 0), new Vector3D(-1, 0, 0)); plotModel.Children.Add(label); } #endregion #region eje z double z0 = (int) (minZ/IntervalZ)*IntervalZ; for (double z = z0; z <= maxZ + double.Epsilon; z += IntervalZ) { GeometryModel3D label = TextCreator.CreateTextLabelModel3D(StringUtils.CodeString(z / ScaleZ), Brushes.Black, true, FontSize, new Point3D(minX - FontSize * 3, maxY, z), new Vector3D(1, 0, 0), new Vector3D(0, 0, 1)); plotModel.Children.Add(label); } { GeometryModel3D label = TextCreator.CreateTextLabelModel3D("Z-axis", Brushes.Black, true, FontSize, new Point3D(minX - FontSize * 10, maxY, (minZ + maxZ)*0.5), new Vector3D(0, 0, 1), new Vector3D(1, 0, 0)); plotModel.Children.Add(label); } #endregion var bb = new Rect3D(minX, minY, minZ, maxX - minX, maxY - minY, 0*(maxZ - minZ)); axesMeshBuilder.AddBoundingBox(bb, LineThickness); var axesModel = new GeometryModel3D(axesMeshBuilder.ToMesh(), Materials.Black); plotModel.Children.Add(surfaceModel); plotModel.Children.Add(axesModel); return plotModel; }
/// <summary> /// Do the tesselation and return the <see cref="MeshGeometry3D"/> . /// </summary> /// <returns> /// A triangular mesh geometry. /// </returns> protected override MeshGeometry3D Tessellate() { if (this.Path == null) { return null; } var builder = new MeshBuilder(false, this.TextureCoordinates != null); builder.AddTube( this.Path, this.TextureCoordinates, this.Diameters, this.Section, this.IsPathClosed, this.IsSectionClosed); return builder.ToMesh(); }
/// <summary> /// Add a tube geometry object. /// </summary> /// <param name="shapeName">The 3DView object.</param> /// <param name="path">A space or colon deliminated list of 3D point coordinates.</param> /// <param name="diameter">The tube diameter.</param> /// <param name="divisions">The tube radial divisions, default 10 (affects number of triangles and smoothness).</param> /// <param name="colour">A colour or gradient brush for the object.</param> /// <param name="materialType">A material for the object. /// The available options are: /// "E" Emmissive - constant brightness. /// "D" Diffusive - affected by lights. /// "S" Specular - specular highlights. /// </param> /// <returns>The 3DView Geometry name.</returns> public static Primitive AddTube(Primitive shapeName, Primitive path, Primitive diameter, Primitive divisions, Primitive colour, Primitive materialType) { bool closed = false; UIElement obj; try { if (_objectsMap.TryGetValue((string)shapeName, out obj)) { InvokeHelperWithReturn ret = new InvokeHelperWithReturn(delegate { try { if (obj.GetType() == typeof(Viewport3D)) { MeshBuilder builder = new MeshBuilder(true, true); Point3DCollection pointCollection = new Point3DCollection(); string[] s = Utilities.getString(path).Split(stringSeparators, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < s.Length; i += 3) { pointCollection.Add(new Point3D(Utilities.getDouble(s[i]), Utilities.getDouble(s[i + 1]), Utilities.getDouble(s[i + 2]))); } int thetaDiv = divisions < 2 ? 10 : (int)divisions; builder.AddTube(pointCollection, diameter, thetaDiv, closed); MeshGeometry3D mesh = builder.ToMesh(); Viewport3D viewport3D = (Viewport3D)obj; return AddGeometry(viewport3D, mesh.Positions, mesh.TriangleIndices, mesh.Normals, mesh.TextureCoordinates, colour, materialType); } } catch (Exception ex) { Utilities.OnError(Utilities.GetCurrentMethod(), ex); } return ""; }); return FastThread.InvokeWithReturn(ret).ToString(); } else { Utilities.OnShapeError(Utilities.GetCurrentMethod(), shapeName); } } catch (Exception ex) { Utilities.OnError(Utilities.GetCurrentMethod(), ex); } return ""; }