Beispiel #1
0
        public StreamLinesSample()
        {
            InitializeComponent();


            // We will set the tube path position color based on the Density
            string colorColumnName  = "Density"; // "AngularVelocity"
            bool   invertColorValue = false;     // This needs to be set to true when using AngularVelocity


            // First create a gradient legend and texture
            var gradientStopCollection = new GradientStopCollection();

            gradientStopCollection.Add(new GradientStop(Colors.Red, 1));
            gradientStopCollection.Add(new GradientStop(Colors.Yellow, 0.75));
            gradientStopCollection.Add(new GradientStop(Colors.Lime, 0.5));
            gradientStopCollection.Add(new GradientStop(Colors.Aqua, 0.25));
            gradientStopCollection.Add(new GradientStop(Colors.Blue, 0));

            var linearGradientBrush = new LinearGradientBrush(gradientStopCollection,
                                                              new System.Windows.Point(0, 1),  // startPoint (offset == 0) - note that y axis is down (so 1 is bottom)
                                                              new System.Windows.Point(0, 0)); // endPoint (offset == 1)

            // Create Legend control
            var gradientColorLegend = new GradientColorLegend()
            {
                Width  = 70,
                Height = 200,
                Margin = new Thickness(5, 5, 5, 5)
            };

            gradientColorLegend.GradientBrush = linearGradientBrush;

            var gradientTexture = gradientColorLegend.RenderToTexture(size: 256, isHorizontal: true);

            var imageBrush = new ImageBrush(gradientTexture);

            // IMPORTANT:
            // When texture coordinates have one components (for example y) always set to 0,
            // we need to change the ViewportUnits from the default RelativeToBoundingBox to Absolute.
            imageBrush.ViewportUnits = BrushMappingMode.Absolute;

            var gradientMaterial = new DiffuseMaterial(imageBrush);


            // Now load sample data
            // Sample data was created by using ParaView application and exporting the streamlines into csv file.
            string sampleDataFileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources\\Streamlines.csv");


            // Create csv file reader that can read data from a csv file
            var csvDataReader = new CsvDataReader();

            csvDataReader.ReadFile(sampleDataFileName);


            float minValue, maxValue;

            csvDataReader.GetValuesRange(colorColumnName, out minValue, out maxValue);

            float dataRange = maxValue - minValue;


            var streamlineIndexes = csvDataReader.IndividualObjectIndexes;


            // Create the streamlines
            var allStreamlineBounds = new Rect3D();

            for (var i = 0; i < csvDataReader.IndividualObjectIndexes.Length - 1; i++)
            {
                Rect3D bounds;

                int startIndex = streamlineIndexes[i];
                int endIndex   = streamlineIndexes[i + 1] - 1;

                int dataCount = endIndex - startIndex;

                if (dataCount < 2) // Skip streamlines without any positions or with less then 2 positions
                {
                    continue;
                }

                var positions = csvDataReader.GetPositions(startIndex, dataCount, out bounds);

                allStreamlineBounds.Union(bounds);

                var pathPositions = new Point3DCollection(positions);


                float[] dataValues = csvDataReader.GetValues(colorColumnName, startIndex, dataCount);

                // Generate texture coordinates for each path position
                // Because our texture is one dimensional gradient image (size 256 x 1)
                // we set the x coordinate in range from 0 to 1 (0 = first gradient color; 1 = last gradient color).
                //
                // Note:
                // If we would only set x texture coordinate and preserve y at 0,
                // WPF would not render the texture because the y size would be 0
                // and because by default the ViewportUnits is set to RelativeToBoundingBox,
                // WPF "thinks" the texture is empty.
                // Therefore we need to set the imageBrush.ViewportUnits to Absolute.
                var positionsCount     = pathPositions.Count;
                var textureCoordinates = new PointCollection(positionsCount);
                for (int j = 0; j < dataCount; j++)
                {
                    float relativeDataValue = (dataValues[j] - minValue) / dataRange;

                    if (invertColorValue)
                    {
                        relativeDataValue = 1.0f - relativeDataValue;
                    }

                    textureCoordinates.Add(new Point(relativeDataValue, 0));
                }


                var tubePathMesh3D = new Ab3d.Meshes.TubePathMesh3D(
                    pathPositions: pathPositions,
                    pathPositionTextureCoordinates: textureCoordinates,
                    radius: 0.03,
                    isTubeClosed: true,
                    isPathClosed: false,
                    segments: 8);


                var geometryModel3D = new GeometryModel3D(tubePathMesh3D.Geometry, gradientMaterial);
                //var geometryModel3D = new GeometryModel3D(tubePathMesh3D.Geometry, new DiffuseMaterial(Brushes.Red));
                geometryModel3D.BackMaterial = new DiffuseMaterial(Brushes.DimGray);

                var modelVisual3D = new ModelVisual3D()
                {
                    Content = geometryModel3D
                };

                MainViewport.Children.Add(modelVisual3D);
            }

            Camera1.TargetPosition = allStreamlineBounds.GetCenterPosition();
            Camera1.Distance       = allStreamlineBounds.GetDiagonalLength();


            // Add legend control:
            int legendValuesCount = 5;

            for (int i = 0; i < legendValuesCount; i++)
            {
                float t        = (float)i / (float)(legendValuesCount - 1);
                float oneValue = minValue + t * (maxValue - minValue);

                string valueLegendText = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:0.00}", oneValue);
                gradientColorLegend.LegendLabels.Add(new GradientColorLegend.LegendLabel(t, valueLegendText));
            }


            var legendTitleTextBlock = new TextBlock()
            {
                Text                = colorColumnName,
                FontSize            = 14,
                FontWeight          = FontWeights.Bold,
                Foreground          = Brushes.Black,
                HorizontalAlignment = HorizontalAlignment.Center
            };


            var stackPanel = new StackPanel()
            {
                Orientation         = Orientation.Vertical,
                VerticalAlignment   = VerticalAlignment.Bottom,
                HorizontalAlignment = HorizontalAlignment.Right,
                Margin = new Thickness(0, 0, 5, 5)
            };

            stackPanel.Children.Add(legendTitleTextBlock);
            stackPanel.Children.Add(gradientColorLegend);

            RootGrid.Children.Add(stackPanel);
        }