Example #1
0
        private PolyLineVisual3D CreatePositionMarker(Point position, Color color)
        {
            var polyLineVisual3D = new PolyLineVisual3D()
            {
                Positions     = new Point3DCollection(5),
                LineColor     = color,
                LineThickness = 1,
            };

            UpdatePositionMarker(polyLineVisual3D, position);

            MarkerLinesVisual3D.Children.Add(polyLineVisual3D);

            return(polyLineVisual3D);
        }
Example #2
0
        private void UpdatePositionMarker(PolyLineVisual3D polyLineVisual3D, Point position, double zPos = 0.5)
        {
            var markerPositions = polyLineVisual3D.Positions;

            markerPositions.Clear(); // Reuse existing Point3DCollection

            double halfSize = _positionMarkerHalfSize;

            double x  = position.X;
            double y  = position.Y;
            double x1 = x - halfSize;
            double y1 = y - halfSize;
            double x2 = x + halfSize;
            double y2 = y + halfSize;

            markerPositions.Add(new Point3D(x1, y1, zPos)); // Set z to 0.5 to show marker lines above other lines
            markerPositions.Add(new Point3D(x2, y1, zPos));
            markerPositions.Add(new Point3D(x2, y2, zPos));
            markerPositions.Add(new Point3D(x1, y2, zPos));
            markerPositions.Add(new Point3D(x1, y1, zPos)); // Close the rectangle with duplicating the first position
        }
Example #3
0
        public TwoDimensionalCameraLineEditor()
        {
            InitializeComponent();

            MouseCameraControllerInfo1.AddCustomInfoLine(0, MouseCameraController.MouseAndKeyboardConditions.LeftMouseButtonPressed, "Create new line");


            // NOTE: TwoDimensionalCamera class is available with full source in this samples project in the Common folder.

            // Create an instance of TwoDimensionalCamera.
            // TwoDimensionalCamera will internally create a TargetPositionCamera and MouseCameraController (when mouseEventsSourceElement is not null).
            // They will be used to show the 2D scene.
            _twoDimensionalCamera = new TwoDimensionalCamera(MainDXViewportView,
                                                             mouseEventsSourceElement: ViewportBorder,   // if mouseEventsSourceElement is null, then MouseCameraController will not be created by TwoDimensionalCamera
                                                             useScreenPixelUnits: false,                 // when false, then the size in device independent units is used (as size of DXViewportView); when true size in screen pixels is used (see SharpHorizontalAndVerticalLines sample)
                                                             coordinateSystemType: TwoDimensionalCamera.CoordinateSystemTypes.CenterOfViewOrigin)
            {
                MoveCameraConditions       = MouseCameraController.MouseAndKeyboardConditions.RightMouseButtonPressed,
                QuickZoomConditions        = MouseCameraController.MouseAndKeyboardConditions.LeftMouseButtonPressed | MouseCameraController.MouseAndKeyboardConditions.RightMouseButtonPressed,
                ShowCameraLight            = ShowCameraLightType.Always,
                IsMouseAndTouchZoomEnabled = true,
            };

            // You can access the create TargetPositionCamera with UsedCamera property
            // and MouseCameraController with UsedMouseCameraController property.
            MouseCameraControllerInfo1.MouseCameraController = _twoDimensionalCamera.UsedMouseCameraController;

            // If we want to use LeftMouseButton for mouse movement, then we can also start new line with the same button with setting MouseMoveThreshold:
            //// Set MouseMoveThreshold so that mouse move starts after the mouse is moved
            //// for at least 3 pixels. This way we can use mouse click to start / end line drawing.
            //_twoDimensionalCamera.UsedMouseCameraController.MouseMoveThreshold = 3;


            _twoDimensionalCamera.CameraChanged += delegate(object sender, EventArgs args)
            {
                // When zoom is changed, we need to update all line markers
                if (!MathUtils.IsSame(_lastZoomFactor, _twoDimensionalCamera.ZoomFactor))
                {
                    // Update line markers size (we want that at each zoom level their WPF size is _positionMarkerWpfSize
                    _positionMarkerHalfSize = _twoDimensionalCamera.GetViewSizeFromWpfSize(_positionMarkerWpfSize) * 0.5;

                    if (double.IsNaN(_snappedViewPosition.X)) // Check if _snappedViewPosition is actually set
                    {
                        return;
                    }

                    // Reuse last position
                    var mousePosition = _twoDimensionalCamera.ToWpfPosition(_snappedViewPosition);
                    CheckPositionMarkers(mousePosition, updateExistingPositionMarkers: true); // _positionMarkerHalfSize is changed so we need to update all shown position markers

                    _lastZoomFactor = _twoDimensionalCamera.ZoomFactor;
                }
            };


            _twoDimensionalCamera.UsedMouseCameraController.CameraMoveStarted += delegate(object sender, EventArgs args)
            {
                _isMouseButtonPressed = false; // when we started mouse camera movement, we need to prevent creating the line when the mouse button is released
            };

            _twoDimensionalCamera.UsedMouseCameraController.CameraQuickZoomStarted += delegate(object sender, EventArgs args)
            {
                _isMouseButtonPressed = false; // when we started quick zoom, we need to prevent creating the line when the mouse button is released
            };


            // We store lines in our List of Points.
            // The main purpose of this is that we can have a very fast access to line positions.
            // (if we would read the Positions from MultiLineVisual3D this would be much slower because accessing DependencyProperties and Point3DCollection is very slow).
            _allPositions = new List <Point>();

            // _positionMarkers is a list that stores all created line markers. The size of array is the same as the size of _allPositions
            _positionMarkers = new List <PolyLineVisual3D>();


            // One MultiLineVisual3D will show fully created 3D lines (this is the much faster then creating individual LineVisual3D objects)
            _multiLineVisual3D = new MultiLineVisual3D()
            {
                Positions     = new Point3DCollection(),
                LineColor     = Colors.Black,
                LineThickness = 1
            };

            MainViewport.Children.Add(_multiLineVisual3D);


            // _creatingLine will show the line that is currently being created - user has not placed the end position yet.
            _creatingLine = new LineVisual3D()
            {
                LineColor     = Colors.Gray,
                LineThickness = 1,
                IsVisible     = false
            };

            MainViewport.Children.Add(_creatingLine);


            // _snappedPositionMarker will be shown over standard gray position marker and will indicate with its black color that mouse position is snapped to the marked position.
            _snappedPositionMarker = new PolyLineVisual3D()
            {
                Positions     = new Point3DCollection(5),
                LineColor     = Colors.Black,
                LineThickness = 1,
                IsVisible     = false
            };

            MainViewport.Children.Add(_snappedPositionMarker);


            _positionMarkerHalfSize = _twoDimensionalCamera.GetViewSizeFromWpfSize(_positionMarkerWpfSize) * 0.5;

            AddAxisLines();

            AddRandomLines(10);

            _snappedViewPosition = new Point(double.NaN, double.NaN); // Mark as invalid


            // We use ViewportBorder to get our mouse events
            ViewportBorder.MouseLeftButtonDown += delegate(object o, MouseButtonEventArgs args)
            {
                _isMouseButtonPressed = true; // we will start the line on mouse up
            };

            ViewportBorder.MouseLeftButtonUp += delegate(object sender, MouseButtonEventArgs args)
            {
                if (!_isMouseButtonPressed)
                {
                    return;
                }

                if (_creatingLine.IsVisible)
                {
                    CompleteNewLine();
                }
                else
                {
                    StartNewLine(_snappedViewPosition);
                }

                _isMouseButtonPressed = false;
            };

            ViewportBorder.MouseMove += delegate(object o, MouseEventArgs args)
            {
                var mousePosition = args.GetPosition(ViewportBorder);
                CheckPositionMarkers(mousePosition, updateExistingPositionMarkers: false);

                if (_creatingLine.IsVisible)
                {
                    UpdateLastLinePosition(_snappedViewPosition);
                }
            };


            this.Unloaded += delegate(object sender, RoutedEventArgs args)
            {
                MainDXViewportView.Dispose();
            };
        }
        private void CreateShapesSample()
        {
            //
            // First create a few lines
            //
            for (int i = 0; i < 5; i++)
            {
                // 2D coordinates of the line
                double x1 = -300;
                double y1 = -50 + i * 20;

                double x2 = -250;
                double y2 = i * 20;

                var lineVisual3D = new LineVisual3D()
                {
                    // Because we use 3D engine to show 2D lines, we need to convert 2D coordinates to 3D coordinates.
                    // This is done with setting Z to 0 (but we could use that to move some lines or shapes in front of the other lines).
                    StartPosition = new Point3D(x1, y1, 0),
                    EndPosition   = new Point3D(x2, y2, 0),
                    LineColor     = Colors.Black,
                    LineThickness = i + 1
                };

                RootLinesVisual3D.Children.Add(lineVisual3D);
            }


            //
            // Create a polyline
            //
            var polygonPositions = new Point3DCollection(new Point3D[]
            {
                new Point3D(-70, -50, 0),
                new Point3D(-170, -50, 0),
                new Point3D(-170, 50, 0),
                new Point3D(-70, 50, 0),
            });

            var polyLineVisual3D = new PolyLineVisual3D()
            {
                Positions     = polygonPositions,
                LineColor     = Colors.Black,
                LineThickness = 1,
                IsClosed      = true
            };

            RootLinesVisual3D.Children.Add(polyLineVisual3D);


            //
            // Create 2 lines with pattern (see LinesWithPatternSample for more info)
            //
            var lineWithPattern1 = new Ab3d.Visuals.LineVisual3D()
            {
                StartPosition = new Point3D(-300, -100, 0),
                EndPosition   = new Point3D(300, -100, 0),
                LineThickness = 2,
                LineColor     = Colors.Orange
            };

            lineWithPattern1.SetDXAttribute(DXAttributeType.LinePattern, 0x3333); // 0x3333 is 0011001100110011
            //lineWithPattern1.SetDXAttribute(DXAttributeType.LinePatternScale,  1); // We do not need to set default scale and offset values
            //lineWithPattern1.SetDXAttribute(DXAttributeType.LinePatternOffset, 0);

            RootLinesVisual3D.Children.Add(lineWithPattern1);


            var lineWithPattern2 = new Ab3d.Visuals.LineVisual3D()
            {
                StartPosition = new Point3D(-300, -110, 0),
                EndPosition   = new Point3D(300, -110, 0),
                LineThickness = 2,
                LineColor     = Colors.Orange
            };

            lineWithPattern2.SetDXAttribute(DXAttributeType.LinePattern, 0x5555); // 0x3333 is 0101010101010101

            RootLinesVisual3D.Children.Add(lineWithPattern2);


            //
            // Create curve with BezierCurve class from Ab3d.PowerToys library (see Lines3D/CurvesSample in Ab3d.PowerToys samples project for more)
            //
            // NOTE:
            // Ab3d.DXEngine cannot show real curves but only straight lines.
            // But you can convert a curve to many lines to simulate a curve (but this may be seen when zooming in).
            //
            var curveControlPoints = new Point3D[]
            {
                new Point3D(0, 0, 0),
                new Point3D(30, 0, 0),
                new Point3D(60, 50, 0),
                new Point3D(90, 0, 0),
                new Point3D(120, 0, 0)
            };

            var bezierCurve    = Ab3d.Utilities.BezierCurve.CreateFromCurvePositions(curveControlPoints);
            var curvePositions = bezierCurve.CreateBezierCurve(positionsPerSegment: 20); // create 20 positions between each control point

            var curveLineVisual3D = new PolyLineVisual3D()
            {
                Positions     = curvePositions,
                LineColor     = Colors.Green,
                LineThickness = 2,
                Transform     = new TranslateTransform3D(0, -50, 0)
            };

            RootLinesVisual3D.Children.Add(curveLineVisual3D);


            //
            // Create lines from a WPF ellipse or any other WPF's shape
            //
            var ellipseGeometry = new EllipseGeometry(new Rect(0, 0, 120, 50));
            var flattenGeometry = ellipseGeometry.GetFlattenedPathGeometry(tolerance: 0.1, type: ToleranceType.Absolute);

            var geometryPoints = new List <Point>();

            geometryPoints.Add(flattenGeometry.Figures[0].StartPoint);

            // We need only the first Figure
            foreach (var oneSegment in flattenGeometry.Figures[0].Segments)
            {
                if (oneSegment is PolyLineSegment)
                {
                    geometryPoints.AddRange(((PolyLineSegment)oneSegment).Points);
                }
                else if (oneSegment is LineSegment)
                {
                    geometryPoints.Add(((LineSegment)oneSegment).Point);
                }
            }

            var ellipsePoints = ConvertToPoint3DCollection(geometryPoints);

            var ellipseLineVisual3D = new PolyLineVisual3D()
            {
                Positions     = ellipsePoints,
                LineColor     = Colors.Green,
                LineThickness = 2,
                Transform     = new TranslateTransform3D(0, 20, 0)
            };

            RootLinesVisual3D.Children.Add(ellipseLineVisual3D);


            //
            // Show 2D shapes with using triangulator from Ab3d.PowerToys to convert shape to a set of triangles.
            //
            // NOTE:
            // The current version (Ab3d.PowerToys v9.4) does not support triangulating shapes with holes.
            //
            var shapePoints = new Point[]
            {
                new Point(0, 0),
                new Point(50, 0),
                new Point(100, 50),
                new Point(100, 100),
                new Point(50, 80),
                new Point(50, 40),
                new Point(0, 40),
                new Point(0, 0),
            };

            var triangulator    = new Ab3d.Utilities.Triangulator(shapePoints);
            var triangleIndices = triangulator.CreateTriangleIndices();

            var shapePoints3D = ConvertToPoint3DCollection(shapePoints);

            var meshGeometry3D = new MeshGeometry3D()
            {
                Positions       = shapePoints3D,
                TriangleIndices = new Int32Collection(triangleIndices)
            };

            var shapeGeometryModel3D = new GeometryModel3D(meshGeometry3D, new DiffuseMaterial(Brushes.LightBlue));

            // NOTE:
            // We set Z of the shape to -0.5 !!!
            // This will move the solid shape slightly behind the 3D line so the line will be always on top of the shape
            shapeGeometryModel3D.Transform = new TranslateTransform3D(200, -50, -0.5);

            RootLinesVisual3D.Children.Add(shapeGeometryModel3D.CreateModelVisual3D());


            // Also add an outline to the shape
            var shapeOutlineVisual3D = new PolyLineVisual3D()
            {
                Positions     = shapePoints3D,
                LineColor     = Colors.Black,
                LineThickness = 1,
                Transform     = shapeGeometryModel3D.Transform
            };

            RootLinesVisual3D.Children.Add(shapeOutlineVisual3D);
        }
        private void LoadSampleLinesData(double lineThickness, Rect targetRect)
        {
            // Read many lines from a custom bin file format.
            // The bin file was created from a metafile (wmf) file that was read by Ab2d.ReaderWmf,
            // then the lines were grouped by color and saved to a custom bin file.

            Rect bounds;
            var  lines = ReadLineDataFromBin(AppDomain.CurrentDomain.BaseDirectory + @"Resources\palazz_sport.bin", out bounds);


            Point targetCenter = new Point(targetRect.X + targetRect.Width * 0.5, targetRect.Y + targetRect.Height * 0.5);

            double xScale = targetRect.Width / bounds.Width;
            double yScale = targetRect.Height / bounds.Height;

            double scale = Math.Min(xScale, yScale); // Preserve aspect ratio - so use the minimal scale

            double xOffset = targetCenter.X - bounds.Width * scale * 0.5;
            double yOffset = targetCenter.Y + bounds.Height * scale * 0.5; // targetCenter.Y - bounds.Height * scale * 0.5 + bounds.Height * scale // because we flipped y we need to offset by height


            var matrixTransform = new MatrixTransform(scale, 0,
                                                      0, -scale, // We also need to flip y axis because here y axis is pointing up
                                                      xOffset, yOffset);

            for (var i = 0; i < lines.Count; i++)
            {
                var oneLineData = lines[i];
                var positions   = oneLineData.Positions;

                var point3DCollection = new Point3DCollection(positions.Count);
                for (var j = 0; j < positions.Count; j++)
                {
                    var p = new Point(positions[j].X, positions[j].Y);
                    p = matrixTransform.Transform(p);

                    point3DCollection.Add(new Point3D(p.X, p.Y, 0));
                }

                if (oneLineData.IsLineStrip)
                {
                    var polyLineVisual3D = new PolyLineVisual3D()
                    {
                        Positions     = point3DCollection,
                        LineColor     = oneLineData.LineColor,
                        LineThickness = lineThickness < 0 ? oneLineData.LineThickness : lineThickness
                    };

                    RootLinesVisual3D.Children.Add(polyLineVisual3D);
                }
                else
                {
                    var multiLineVisual3D = new MultiLineVisual3D()
                    {
                        Positions     = point3DCollection,
                        LineColor     = oneLineData.LineColor,
                        LineThickness = lineThickness < 0 ? oneLineData.LineThickness : lineThickness
                    };

                    RootLinesVisual3D.Children.Add(multiLineVisual3D);
                }
            }
        }
Example #6
0
        private void CreateOffline3DScene()
        {
            var viewport3D = new Viewport3D();

            // IMPORTANT !!!
            // Because this Viewport3D will not be actually shown, we need to manually set its size
            // because this is needed for projection matrix.
            viewport3D.Width  = 800;
            viewport3D.Height = 600;

            var targetPositionCamera = new TargetPositionCamera()
            {
                Heading          = 0,
                Attitude         = 0,
                CameraType       = BaseCamera.CameraTypes.OrthographicCamera,
                CameraWidth      = viewport3D.Width, // Use same width as viewport3D so we get 1:1 scale
                TargetViewport3D = viewport3D
            };

            var polyLineVisual3D = new PolyLineVisual3D()
            {
                Positions = new Point3DCollection(new Point3D[]
                {
                    //new Point3D(-100,   0, -50),
                    //new Point3D(100, 0, -50),
                    //new Point3D(100, 0, 50),
                    //new Point3D(50, 0, 0),
                    //new Point3D(-100,   0, 50),

                    new Point3D(-100, -50, 0),
                    new Point3D(100, -50, 0),
                    new Point3D(100, 50, 0),
                    new Point3D(50, 0, 0),
                    new Point3D(-100, 50, 0),
                }),
                LineColor     = Colors.Green,
                LineThickness = 30,

                // NOTE:
                // If you require that each line segment uses exactly 4 positions,
                // then you need to disable turning mitered joints into beveled joints
                // (beveled joints have 3 additional positions that cut the sharp joint).
                // It is not possible to know in advance how many bevel joints will be
                // because this also depends on the angle of the camera.
                // To disable creating beveled joints set MiterLimit to some high number
                // (for example the following will create a beveled joint when the joint length is 100 times the line thickness).
                //MiterLimit = 100
            };

            viewport3D.Children.Add(polyLineVisual3D);


            targetPositionCamera.Refresh();
            Ab3d.Utilities.LinesUpdater.Instance.Refresh(); // Force regeneration of all 3D lines


            var geometryModel3D = polyLineVisual3D.Content as GeometryModel3D;

            if (geometryModel3D != null)
            {
                var lineMesh = (MeshGeometry3D)geometryModel3D.Geometry;

                _shownLineModel3D              = new GeometryModel3D();
                _shownLineModel3D.Geometry     = lineMesh;
                _shownLineModel3D.Material     = new DiffuseMaterial(Brushes.LightGray);
                _shownLineModel3D.BackMaterial = new DiffuseMaterial(Brushes.Black);

                if (BillboardCheckbox.IsChecked ?? false)
                {
                    ApplyBillboardMatrix();
                }

                MainViewport.Children.Add(_shownLineModel3D.CreateContentVisual3D());

                MeshInspector.MeshGeometry3D = lineMesh;
            }
        }