public VelocityVisualizer3DWindow()
        {
            InitializeComponent();

            // Camera Trackball
            _trackball = new TrackBallRoam(_camera);
            _trackball.EventSource = grdViewPort;		//NOTE:  If this control doesn't have a background color set, the trackball won't see events (I think transparent is ok, just not null)
            _trackball.AllowZoomOnMouseWheel = true;
            _trackball.MouseWheelScale *= .1d;
            _trackball.Mappings.AddRange(TrackBallMapping.GetPrebuilt(TrackBallMapping.PrebuiltMapping.MouseComplete));
            //_trackball.GetOrbitRadius += new GetOrbitRadiusHandler(Trackball_GetOrbitRadius);

            // Velocity line visual
            _velocityLines = new BillboardLine3DSet();
            _velocityLines.Color = Colors.GhostWhite;
            _velocityLines.IsReflectiveColor = true;
            _viewport.Children.Add(_velocityLines);

            UpdateLinePlacement();

            ShowHideBlockedCells();
        }
        private void AddLines_Billboard(IEnumerable<Tuple<int, int>> lines, Point3D[] points, double thickness, Color color)
        {
            BillboardLine3DSet visual = new BillboardLine3DSet();
            visual.Color = color;
            visual.BeginAddingLines();

            foreach (Tuple<int, int> line in lines)
            {
                visual.AddLine(points[line.Item1], points[line.Item2], thickness);
            }

            visual.EndAddingLines();

            _viewport.Children.Add(visual);
            _visuals.Add(visual);
        }
 private void Window_Closed(object sender, EventArgs e)
 {
     try
     {
         if (_velocityLines != null)
         {
             _velocityLines.Dispose();
             _velocityLines = null;
         }
     }
     catch (Exception ex)
     {
         MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
     }
 }
        private static void AddPolyLines(BillboardLine3DSet lines, Point3D[] polygon, double thickness)
        {
            for (int cntr = 0; cntr < polygon.Length - 1; cntr++)
            {
                lines.AddLine(polygon[cntr], polygon[cntr + 1], thickness);
            }

            lines.AddLine(polygon[polygon.Length - 1], polygon[0], thickness);
        }
        private void RedrawPoints()
        {
            // Clear old
            _viewport.Children.RemoveAll(_visuals);
            _visuals.Clear();

            if (_points == null || _points.Length == 0)
            {
                return;
            }

            #region Points

            Model3DGroup geometries = new Model3DGroup();

            for (int cntr = 0; cntr < _points.Length; cntr++)
            {
                Color color = UtilityWPF.AlphaBlend(Colors.Black, UtilityWPF.ColorFromHex("08000000"), _points[cntr].Value);

                // Material
                MaterialGroup materials = new MaterialGroup();
                materials.Children.Add(new DiffuseMaterial(new SolidColorBrush(color)));
                materials.Children.Add(new SpecularMaterial(new SolidColorBrush(UtilityWPF.AlphaBlend(color, Colors.White, .5d)), 100d));

                // Geometry Model
                GeometryModel3D geometry = new GeometryModel3D();
                geometry.Material = materials;
                geometry.BackMaterial = materials;
                geometry.Geometry = UtilityWPF.GetSphere_LatLon(2, DOTRADIUS);

                geometry.Transform = new TranslateTransform3D(_points[cntr].Point.ToVector3D());

                geometries.Children.Add(geometry);
            }

            ModelVisual3D visual = new ModelVisual3D();
            visual.Content = geometries;

            _visuals.Add(visual);
            _viewport.Children.Add(visual);

            #endregion

            if (radShowTriangles1.IsChecked.Value || radShowTriangles2.IsChecked.Value || radShowContour.IsChecked.Value || radShowContourAndTriangles.IsChecked.Value)
            {
                #region Height Triangles, Contour

                //var triangles = Math2D.GetDelaunayTriangulation(_points.Select(o => o.Point).ToArray(), _points.Select(o => o.Point.ToPoint3D() + new Vector3D(0, 0, o.Value * trkTriangleHeight.Value)).ToArray());
                var triangles = GetDelaunay_ExpandRing(_points, trkTriangleHeight.Value);

                if (radShowTriangles1.IsChecked.Value || radShowContourAndTriangles.IsChecked.Value)
                {
                    #region Triangles (mono color)

                    Color color = UtilityWPF.ColorFromHex("40808080");

                    // Material
                    MaterialGroup materials = new MaterialGroup();
                    materials.Children.Add(new DiffuseMaterial(new SolidColorBrush(color)));
                    materials.Children.Add(new SpecularMaterial(new SolidColorBrush(UtilityWPF.AlphaBlend(UtilityWPF.AlphaBlend(color, Colors.White, .5d), Colors.Transparent, .25d)), 5d));

                    // Geometry Model
                    GeometryModel3D geometry = new GeometryModel3D();
                    geometry.Material = materials;
                    geometry.BackMaterial = materials;
                    geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(triangles.Item2);

                    visual = new ModelVisual3D();
                    visual.Content = geometry;

                    _visuals.Add(visual);
                    _viewport.Children.Add(visual);

                    #endregion
                }
                else if (radShowTriangles2.IsChecked.Value)
                {
                    #region Triangles (height color)

                    geometries = new Model3DGroup();

                    foreach (var triangle in triangles.Item2)
                    {
                        double averageHeight = Math1D.Avg(triangles.Item1[triangle.Index0].Value, triangles.Item1[triangle.Index1].Value, triangles.Item1[triangle.Index2].Value);
                        Color color = UtilityWPF.AlphaBlend(Colors.Black, Colors.White, averageHeight);

                        // Material
                        Material material = UtilityWPF.GetUnlitMaterial(Color.FromArgb(192, color.R, color.G, color.B));     // Don't want reflection, it will just confuse the coloring

                        // Geometry Model
                        GeometryModel3D geometry = new GeometryModel3D();
                        geometry.Material = material;
                        geometry.BackMaterial = material;
                        geometry.Geometry = UtilityWPF.GetMeshFromTriangles(new ITriangleIndexed[] { triangle });

                        geometries.Children.Add(geometry);
                    }

                    visual = new ModelVisual3D();
                    visual.Content = geometries;

                    _visuals.Add(visual);
                    _viewport.Children.Add(visual);

                    #endregion
                }

                if (radShowContour.IsChecked.Value || radShowContourAndTriangles.IsChecked.Value)
                {
                    #region Contours

                    //TODO: Instead of just triangles, make parabola hills
                    //var triangles = GetDelaunay_ExpandRing(_points, trkTriangleHeight.Value);

                    int numContours = Convert.ToInt32(trkNumContours.Value);

                    for (int cntr = 0; cntr < numContours; cntr++)
                    {
                        double height = Convert.ToDouble(cntr + 1) / Convert.ToDouble(numContours + 1);     // one contour would be 50%, two would be 33% and 66%, etc
                        double heightScaled = height * trkTriangleHeight.Value;

                        var polys = Math3D.GetIntersection_Mesh_Plane(triangles.Item2, new Triangle(new Point3D(-1, 0, heightScaled), new Point3D(1, 0, heightScaled), new Point3D(0, 1, heightScaled)));

                        if (polys != null && polys.Length > 0)
                        {
                            BillboardLine3DSet lines = new BillboardLine3DSet();

                            lines.Color = UtilityWPF.AlphaBlend(Colors.Black, Colors.White, height);
                            lines.IsReflectiveColor = false;
                            lines.BeginAddingLines();

                            for (int outer = 0; outer < polys.Length; outer++)
                            {
                                AddPolyLines(lines, polys[outer].Polygon3D, LINETHICKNESS);

                                for (int inner = 0; inner < polys[outer].Holes3D.Length; inner++)
                                {
                                    AddPolyLines(lines, polys[outer].Holes3D[inner], LINETHICKNESS);
                                }
                            }

                            lines.EndAddingLines();

                            _visuals.Add(lines);
                            _viewport.Children.Add(lines);
                        }
                    }

                    #endregion
                }

                if (chkShowTriangleEdges.IsChecked.Value)
                {
                    #region Edge Lines

                    BillboardLine3DSet lines = new BillboardLine3DSet();

                    lines.Color = UtilityWPF.ColorFromHex("80808080");
                    lines.IsReflectiveColor = false;
                    lines.BeginAddingLines();

                    Point3D[] trianglePoints = triangles.Item2[0].AllPoints;

                    foreach (var line in TriangleIndexed.GetUniqueLines(triangles.Item2))
                    {
                        lines.AddLine(trianglePoints[line.Item1], trianglePoints[line.Item2], LINETHICKNESS);
                    }

                    lines.EndAddingLines();

                    _visuals.Add(lines);
                    _viewport.Children.Add(lines);

                    #endregion
                }

                #endregion
            }
            else if (radShowLines.IsChecked.Value)
            {
                #region Height Lines

                BillboardLine3DSet lines = new BillboardLine3DSet();

                lines.Color = UtilityWPF.ColorFromHex("80808080");
                lines.IsReflectiveColor = false;
                lines.BeginAddingLines();

                for (int cntr = 0; cntr < _points.Length; cntr++)
                {
                    lines.AddLine(_points[cntr].Point.ToPoint3D(), _points[cntr].Point.ToPoint3D() + new Vector3D(0, 0, _points[cntr].Value * trkTriangleHeight.Value), LINETHICKNESS);
                }

                lines.EndAddingLines();

                _visuals.Add(lines);
                _viewport.Children.Add(lines);

                #endregion
            }
        }
        private void btnContour_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                RedrawPoints();

                if (_points == null || _points.Length == 0)
                {
                    return;
                }

                #region Get terrain triangles

                // Cut a contour slice at the height of trkContourTestHeight
                var triangles = GetDelaunay_ExpandRing(_points, trkTriangleHeight.Value);

                List<TriangleIndexedLinked> trianglesLinked = triangles.Item2.Select(o => new TriangleIndexedLinked(o.Index0, o.Index1, o.Index2, o.AllPoints)).ToList();
                TriangleIndexedLinked.LinkTriangles_Edges(trianglesLinked, true);

                #endregion

                int contourCount = Convert.ToInt32(trkContourTestCount.Value);

                double minHeight = trkContourTestHeight.Value;
                double maxHeight = 1;
                if (chkContourTestHeightIsPercent.IsChecked.Value)
                {
                    double maxValue = _points.Max(o => o.Value);
                    minHeight *= maxValue;
                    maxHeight *= maxValue;
                }

                double heightStep = (maxHeight - minHeight) / Convert.ToDouble(contourCount);

                for (int contourCntr = 0; contourCntr < contourCount; contourCntr++)
                {
                    double height = minHeight + (heightStep * contourCntr);
                    double heightScaled = height * trkTriangleHeight.Value;

                    Triangle plane = new Triangle(new Point3D(-1, 0, heightScaled), new Point3D(1, 0, heightScaled), new Point3D(0, 1, heightScaled));      // normal needs to point up

                    // Get the contour polygons
                    var polys = Math3D.GetIntersection_Mesh_Plane(trianglesLinked.ToArray(), plane);
                    if (polys == null || polys.Length == 0)
                    {
                        return;
                    }

                    #region Get area, volume

                    var densities = polys.Select(o =>
                        {
                            double area = Math2D.GetAreaPolygon(o.Polygon2D);

                            foreach (Point[] hole in o.Holes2D)
                            {
                                area -= Math2D.GetAreaPolygon(hole);
                            }

                            double volume = o.GetVolumeAbove();

                            return new { Area = area, Volume = volume, Density = volume / area };
                        }).ToArray();

                    int winnerIndexArea = 0;
                    int winnerIndexVolume = 0;
                    double maxArea = densities[0].Area;
                    double maxVolume = densities[0].Volume;
                    for (int cntr = 1; cntr < densities.Length; cntr++)
                    {
                        if (densities[cntr].Area > maxArea)
                        {
                            maxArea = densities[cntr].Area;
                            winnerIndexArea = cntr;
                        }

                        if (densities[cntr].Volume > maxVolume)
                        {
                            maxVolume = densities[cntr].Volume;
                            winnerIndexVolume = cntr;
                        }
                    }

                    #endregion

                    #region Draw Poly Islands

                    BillboardLine3DSet holes = null;
                    if (polys.Any(o => o.Holes3D.Length > 0))
                    {
                        holes = new BillboardLine3DSet();

                        holes.Color = UtilityWPF.ColorFromHex("68BAA0BA");
                        holes.IsReflectiveColor = false;
                        holes.BeginAddingLines();
                    }

                    for (int cntr = 0; cntr < polys.Length; cntr++)
                    {
                        // Main polygon
                        BillboardLine3DSet lines = new BillboardLine3DSet();

                        if (cntr == winnerIndexArea && cntr == winnerIndexVolume)
                        {
                            lines.Color = Color.FromRgb(192, 64, 192);
                        }
                        else if (cntr == winnerIndexArea)
                        {
                            lines.Color = Color.FromRgb(192, 64, 64);
                        }
                        else if (cntr == winnerIndexVolume)
                        {
                            lines.Color = Color.FromRgb(64, 64, 192);
                        }
                        else
                        {
                            lines.Color = UtilityWPF.GetRandomColor(255, 64, 64, 100, 200, 64, 64);
                        }

                        lines.IsReflectiveColor = false;
                        lines.BeginAddingLines();

                        AddPolyLines(lines, polys[cntr].Polygon3D, LINETHICKNESS);

                        // Winner Point
                        if (cntr == winnerIndexArea || cntr == winnerIndexVolume)
                        {
                            Point3D polyCenter = Math3D.GetCenter(polys[cntr].Polygon3D);

                            lines.AddLine(new Point3D(polyCenter.X, polyCenter.Y, 0), new Point3D(polyCenter.X, polyCenter.Y, RADIUS * 2), LINETHICKNESS * 2);
                        }

                        //// Volume
                        //lines.AddLine(polys[cntr].Polygon3D[0], polys[cntr].Polygon3D[0] + new Vector3D(0, 0, densities[cntr].Volume * 10), LINETHICKNESS * 5);

                        //// Area
                        //int halfIndex = polys[cntr].Polygon3D.Length / 2;
                        //lines.AddLine(polys[cntr].Polygon3D[halfIndex], polys[cntr].Polygon3D[halfIndex] + new Vector3D(0, 0, densities[cntr].Area * 10), LINETHICKNESS);

                        ////Density just doesn't seem to add value.  The height will attract a larger polygon, so relating volume to area doesn't make much sense
                        //// Density
                        //int quarterIndex = polys[cntr].Polygon3D.Length / 4;
                        //lines.AddLine(polys[cntr].Polygon3D[quarterIndex], polys[cntr].Polygon3D[quarterIndex] + new Vector3D(0, 0, densities[cntr].Density * 10), LINETHICKNESS * 2);

                        lines.EndAddingLines();

                        _visuals.Add(lines);
                        _viewport.Children.Add(lines);

                        // Holes
                        foreach (Point3D[] polyHole in polys[cntr].Holes3D)
                        {
                            AddPolyLines(holes, polyHole, LINETHICKNESS);
                        }
                    }

                    if (holes != null)
                    {
                        holes.EndAddingLines();

                        _visuals.Add(holes);
                        _viewport.Children.Add(holes);
                    }

                    #endregion
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
示例#7
0
        private static void DrawLine(Point3D position, Vector3D direction, Color color, Viewport3D viewport, List<Visual3D> debugVisuals)
        {
            BillboardLine3DSet line = new BillboardLine3DSet()
            {
                Color = color,
                IsReflectiveColor = false,
            };

            line.BeginAddingLines();
            line.AddLine(position, position + direction, .2);
            line.EndAddingLines();

            debugVisuals.Add(line);
            viewport.Children.Add(line);
        }
        private static Visual3D AddLines(Viewport3D viewport, IEnumerable<Tuple<Point3D, Point3D>> lines, Color color, double thickness = .015)
        {
            BillboardLine3DSet retVal = new BillboardLine3DSet();
            retVal.Color = color;
            retVal.BeginAddingLines();

            foreach (Tuple<Point3D, Point3D> line in lines)
            {
                retVal.AddLine(line.Item1, line.Item2, thickness);
            }

            retVal.EndAddingLines();

            viewport.Children.Add(retVal);
            return retVal;
        }