예제 #1
0
        CanvasGeometry MakeCircleGeometry()
        {
            bool first = true;
            Rect bounds;

            foreach (var point in currentPointsInContact.Values)
            {
                if (first)
                {
                    bounds = new Rect(point, point);
                    first  = false;
                }
                else
                {
                    bounds.Union(point);
                }
            }

            var radius = Math.Max(bounds.Width, bounds.Height) * 0.5;

            if (radius == 0)
            {
                radius = 50;
            }

            var center = new Vector2((float)(bounds.Left + bounds.Width * 0.5), (float)(bounds.Top + bounds.Height * 0.5));

            return(CanvasGeometry.CreateCircle(device, center, (float)radius));
        }
예제 #2
0
        private void StartClip(Visual visual, bool show, Vector2 desiredSize)
        {
            var actualWidth  = desiredSize.X;
            var actualHeight = desiredSize.Y;
            var left         = (float)Padding.Left;
            var top          = (float)Padding.Top;

            var width    = MathF.Max(actualWidth - left, actualHeight - top);
            var diaginal = MathF.Sqrt((width * width) + (width * width));

            var device = CanvasDevice.GetSharedDevice();

            var rect1 = CanvasGeometry.CreateRectangle(device, 0, 0, show ? 0 : actualWidth, show ? 0 : actualHeight);

            var elli1  = CanvasGeometry.CreateCircle(device, left, top, 0);
            var group1 = CanvasGeometry.CreateGroup(device, new[] { elli1, rect1 }, CanvasFilledRegionDetermination.Alternate);

            var elli2  = CanvasGeometry.CreateCircle(device, left, top, diaginal);
            var group2 = CanvasGeometry.CreateGroup(device, new[] { elli2, rect1 }, CanvasFilledRegionDetermination.Alternate);

            var ellipse = Window.Current.Compositor.CreatePathGeometry(new CompositionPath(group2));
            var clip    = Window.Current.Compositor.CreateGeometricClip(ellipse);

            var ease = Window.Current.Compositor.CreateCubicBezierEasingFunction(new Vector2(.42f, 0), new Vector2(1, 1));
            var anim = Window.Current.Compositor.CreatePathKeyFrameAnimation();

            anim.InsertKeyFrame(0, new CompositionPath(group1), ease);
            anim.InsertKeyFrame(1, new CompositionPath(group2), ease);
            anim.Duration = TimeSpan.FromMilliseconds(500);

            ellipse.StartAnimation("Path", anim);
            visual.Clip = clip;
        }
예제 #3
0
        public void AddCircle(float x, float y, float radius)
        {
            InvalidateGeometry();

            var geometry = CanvasGeometry.CreateCircle(Device, x, y, radius);

            AddGeometry(geometry);
        }
예제 #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="appCtx"></param>
        /// <param name="canvas"></param>
        /// <param name="drawableEdges"></param>
        /// <param name="drawableVertices"></param>
        public static void LayoutDGraphRandom(
            AppContext appCtx,
            CanvasControl canvas,
            Dictionary <Guid, DrawableEdge> drawableEdges,
            Dictionary <Guid, DrawableVertex> drawableVertices)
        {
            drawableEdges.Clear();
            drawableVertices.Clear();
            foreach (KeyValuePair <Guid, UVertex> kvp in appCtx.CurrentGraph.Vertices)
            {
                Int32 min_x = Defines.VERTEX_SIZE;
                Int32 min_y = Defines.VERTEX_SIZE;
                Int32 max_x = 0;
                Int32 max_y = 0;
                if (appCtx.FitGraphToView == true)
                {
                    max_x = (Int32)canvas.ActualWidth - Defines.VERTEX_SIZE;
                    max_y = (Int32)canvas.ActualHeight - Defines.VERTEX_SIZE;
                }
                else
                {
                    max_x = Defines.VERTEX_SIZE * (appCtx.CurrentGraph.Vertices.Count + Defines.MAX_VERTEX_SPACE);
                    max_y = Defines.VERTEX_SIZE * (appCtx.CurrentGraph.Vertices.Count + Defines.MAX_VERTEX_SPACE);
                }

                Vector2        circlePos = new Vector2(appCtx.RandomSource.Next(min_x, max_x), appCtx.RandomSource.Next(min_y, max_y));
                DrawableVertex dn        = new DrawableVertex
                {
                    Position = circlePos,
                    VertexId = kvp.Value.VertexId,
                    Circle   = CanvasGeometry.CreateCircle(canvas, circlePos, Defines.VERTEX_SIZE)
                };
                drawableVertices[dn.VertexId] = dn;
            }

            foreach (KeyValuePair <Guid, UEdge> kvp in appCtx.CurrentGraph.Edges)
            {
                CanvasPathBuilder pathBuilder = new CanvasPathBuilder(canvas);

                DrawableEdge de = new DrawableEdge
                {
                    EdgeId       = kvp.Value.EdgeId,
                    HeadVertexId = kvp.Value.HeadVertexId,
                    TailVertexId = kvp.Value.TailVertexId,
                };
                de.HeadPosition = drawableVertices[de.HeadVertexId].Position;
                de.TailPosition = drawableVertices[de.TailVertexId].Position;
                pathBuilder.BeginFigure(de.HeadPosition);
                pathBuilder.AddLine(de.TailPosition);
                pathBuilder.EndFigure(CanvasFigureLoop.Open);
                de.Line = CanvasGeometry.CreatePath(pathBuilder);
                drawableEdges[de.EdgeId] = de;
            }

            canvas.Invalidate();
        }
예제 #5
0
        public void CreateResources(ICanvasResourceCreator resourceCreator)
        {
            DestroyResources();

            // create stroke
            _strokeStyle = new CanvasStrokeStyle();

            // create geometry
            var body   = CanvasGeometry.CreateCircle(resourceCreator, new Vector2(0.0f), 24);
            var cannon = CanvasGeometry.CreateRectangle(resourceCreator, 23, -3, 10, 6);

            var comb = body.CombineWith(cannon, Matrix3x2.Identity, CanvasGeometryCombine.Union);

            // cache
            _geo = CanvasCachedGeometry.CreateStroke(comb, Style.StrokeWidth, _strokeStyle);
        }
        private CanvasGeometry?CreateOverlayMask(IDrawingCanvas sender)
        {
            var _canvas = sender;

            if (_canvas == null)
            {
                return(null);
            }
            return(CanvasGeometry
                   .CreateCircle(sender, _canvas.Center.ToVector2() * _canvas.Size.ToVector2(), (float)(OuterRadius * _canvas.Size.Height))
                   .CombineWith(
                       CanvasGeometry.CreateRectangle(sender, Bounds.GetRectangle(_canvas)),
                       Matrix3x2.Identity,
                       CanvasGeometryCombine.Intersect)
                   .CombineWith(
                       CanvasGeometry.CreateCircle(sender, _canvas.Center.ToVector2() * _canvas.Size.ToVector2(), (float)(InnerRadius * _canvas.Size.Height)),
                       Matrix3x2.Identity,
                       CanvasGeometryCombine.Exclude
                       ));
        }
        private CanvasGeometry CreateCanvasGeometry(CanvasVirtualControl device)
        {
            switch (GeometryType)
            {
            case GeometryType.Rectangle:
                return(CanvasGeometry.CreateRectangle(device, (float)Points[0].X, (float)Points[0].Y,
                                                      (float)MapController.Instance.MousePosition.X - (float)Points[0].X, (float)MapController.Instance.MousePosition.Y - (float)Points[0].Y));

            case GeometryType.Line:
                CanvasPathBuilder pathBuilder = new CanvasPathBuilder(device);
                pathBuilder.SetSegmentOptions(CanvasFigureSegmentOptions.ForceRoundLineJoin);
                pathBuilder.BeginFigure((float)Points[0].X, (float)Points[0].Y);
                pathBuilder.AddLine(new Vector2((float)MapController.Instance.MousePosition.X, (float)MapController.Instance.MousePosition.Y));
                pathBuilder.EndFigure(CanvasFigureLoop.Open);
                return(CanvasGeometry.CreatePath(pathBuilder));

            case GeometryType.Circle:
                return(CanvasGeometry.CreateCircle(device, new Vector2((float)Points[0].X, (float)Points[0].Y), GetSegmentLength.CalculateSegmentLength(Points[0], MapController.Instance.MousePosition)));
            }
            return(null);
        }
예제 #8
0
        public void LayoutGraphRandom(CanvasControl canvas)
        {
            this.Layout = DrawableGraphLayout.Random;

            foreach (KeyValuePair <UInt32, GraphVertex> kvp in this.Vertices)
            {
                UInt32 minX         = Defines.VERTEX_SIZE;
                UInt32 minY         = Defines.VERTEX_SIZE;
                UInt32 maxX         = 0;
                UInt32 maxY         = 0;
                UInt32 paddingValue = Defines.VERTEX_SIZE - Defines.MAX_VERT_SPACE;
                if (this.FitToView == true)
                {
                    maxX = (UInt32)canvas.ActualWidth - paddingValue;
                    maxY = (UInt32)canvas.ActualHeight - paddingValue;
                }
                else
                {
                    maxX = Defines.VERTEX_SIZE * ((UInt32)this.Vertices.Count + Defines.MAX_VERT_SPACE);
                    maxY = maxX;
                }

                kvp.Value.Position = new Vector2(
                    this.rng.Next((Int32)minX, (Int32)maxX),
                    this.rng.Next((Int32)minY, (Int32)maxY));
                kvp.Value.Circle = CanvasGeometry.CreateCircle(canvas, kvp.Value.Position, kvp.Value.VertexSize);
            }

            foreach (KeyValuePair <UInt32, GraphEdge> kvp in this.Edges)
            {
                CanvasPathBuilder pathBuilder = new CanvasPathBuilder(canvas);
                kvp.Value.HeadPosition = this.Vertices[kvp.Value.HeadVertexId].Position;
                kvp.Value.TailPosition = this.Vertices[kvp.Value.TailVertexId].Position;
                pathBuilder.BeginFigure(kvp.Value.HeadPosition);
                pathBuilder.AddLine(kvp.Value.TailPosition);
                pathBuilder.EndFigure(CanvasFigureLoop.Open);
                kvp.Value.Line = CanvasGeometry.CreatePath(pathBuilder);
            }
        }
예제 #9
0
        private void DrawIdleBg(CanvasDrawingSession ds)
        {
            Easings.ParamTween(ref BgY_c, BgY_t, 0.85f, 0.15f);
            BgFillRect.Y = BgY_c;

            Easings.ParamTween(ref BgR_c, BgR_t, 0.75f, 0.25f);
            if (BgR_c < 0)
            {
                ds.DrawImage(BgBmp, StageRect, BgFillRect);
                ds.FillRectangle(StageRect, MaskBrush);
            }
            else
            {
                ds.DrawImage(BgBmp, StageRect, BgFillRect);

                CanvasGeometry MaskFill  = CanvasGeometry.CreateRectangle(ds, StageRect);
                CanvasGeometry DrillMask = CanvasGeometry.CreateCircle(ds, PCenter, BgR_c);
                CanvasGeometry Combined  = MaskFill.CombineWith(DrillMask, Matrix3x2.CreateTranslation(0, 0), CanvasGeometryCombine.Exclude);

                ds.FillGeometry(Combined, MaskBrush);
            }
        }
예제 #10
0
        private void CreateCanvasGeometry(CanvasVirtualControl device)
        {
            switch (GeometryType)
            {
            case GeometryType.Rectangle:
                _geometry = CanvasGeometry.CreateRectangle(device, (float)Points[0].X, (float)Points[0].Y,
                                                           (float)Points[1].X - (float)Points[0].X, (float)Points[1].Y - (float)Points[0].Y);
                break;

            case GeometryType.Line:
                _geometry = CanvasGeometry.CreatePolygon(device,
                                                         new Vector2[]
                {
                    new Vector2((float)Points[0].X, (float)Points[0].Y),
                    new Vector2((float)Points[1].X, (float)Points[1].Y)
                });
                break;

            case GeometryType.Circle:
                _geometry = CanvasGeometry.CreateCircle(device, new Vector2((float)Points[0].X, (float)Points[0].Y), GetSegmentLength.CalculateSegmentLength(Points[0], Points[1]));
                break;
            }
        }
예제 #11
0
 public static CanvasGeometry CreateCircle(ICanvasResourceCreator resourceCreator)
 {
     return(CanvasGeometry.CreateCircle(resourceCreator, 500, 20, 20));
 }
예제 #12
0
        private async void OnPageLoaded(object sender, RoutedEventArgs e)
        {
            _compositor = Window.Current.Compositor;
            _generator  = _compositor.CreateCompositionGenerator();
            var gridSize = new Vector2((float)RootGrid.ActualWidth, (float)RootGrid.ActualHeight);
            var anim     = _compositor.CreatePathKeyFrameAnimation();

            _rootVisual      = _compositor.CreateSpriteVisual();
            _rootVisual.Size = gridSize;

            // Create the surface brush from the image
            var imageSurface = await _generator.CreateImageSurfaceAsync(
                new Uri("ms-appx:///Assets/Images/Cat.png"),
                new Size(400, 400),
                ImageSurfaceOptions.Default);

            var imageBrush = _compositor.CreateSurfaceBrush(imageSurface);

            // Create the clipped visuals
            for (var i = 0; i < 145; i++)
            {
                var visual = _compositor.CreateSpriteVisual();
                visual.Offset      = new Vector3(400, 400, 0);
                visual.Size        = new Vector2(400, 400);
                visual.Brush       = imageBrush;
                visual.AnchorPoint = new Vector2(0.5f);
                var radius = 290 - (i * 2);
                // Create the GeometricClip for this visual
                var clipGeometry = CanvasGeometry.CreateCircle(null, new Vector2(200, 200), radius);
                visual.Clip = _compositor.CreateGeometricClip(clipGeometry);

                _rootVisual.Children.InsertAtTop(visual);
                _visuals.Add(visual);
            }

            // Display the rootVisual
            ElementCompositionPreview.SetElementChildVisual(RootGrid, _rootVisual);

            // Reverse the visuals list so that the items in the list are now sorted
            // in z-order from top to bottom
            _visuals.Reverse();
            // The topmost visual would track the pointer position
            _dragVisual = _visuals.First();

            // Get the CompositionPropertySet which tracks the pointer position on the RootGrid
            _pointerTrackerSet = ElementCompositionPreview.GetPointerPositionPropertySet(RootGrid);
            // Animate the topmost visual so that it tracks and follows the pointer position
            _pointerTrackerAnimation = _compositor.GenerateVector3KeyFrameAnimation()
                                       .HavingDuration(PointerTrackerAnimationDuration)
                                       .RepeatsForever();

            _pointerTrackerAnimation.InsertExpressionKeyFrame(0f, c => new VisualTarget().Offset);
            _pointerTrackerAnimation.InsertExpressionKeyFrame(
                1f,
                c => c.Lerp(new VisualTarget().Offset, _pointerTrackerSet.Get <Vector3>("Position"), DefaultLerpAmount),
                _compositor.CreateEaseOutQuinticEasingFunction());

            // Animate the remaining visuals in such a way that each visual tracks and follows the
            // position of the visual above it.
            var prevChild = _dragVisual;

            foreach (var child in _visuals.Skip(1))
            {
                var offsetAnimation = _compositor.GenerateVector3KeyFrameAnimation()
                                      .HavingDuration(ChildOffsetAnimationDuration)
                                      .RepeatsForever();

                offsetAnimation.InsertExpressionKeyFrame(0f, c => new VisualTarget().Offset);
                offsetAnimation.InsertExpressionKeyFrame(
                    1f,
                    c => c.Lerp(new VisualTarget().Offset, prevChild.Offset, DefaultLerpAmount),
                    _compositor.CreateEaseOutQuinticEasingFunction());

                child.StartAnimation(() => child.Offset, offsetAnimation);

                prevChild = child;
            }
        }
        /// <summary>
        /// Handles the Arrange layout phase
        /// </summary>
        /// <param name="finalSize">Final Size of the control</param>
        /// <returns>Size</returns>
        protected override Size ArrangeOverride(Size finalSize)
        {
            if ((_compositor == null) || (_generator == null))
            {
                return(base.ArrangeOverride(finalSize));
            }

            if (Double.IsInfinity(finalSize.Width) || Double.IsInfinity(finalSize.Height) ||
                Double.IsNaN(finalSize.Width) || Double.IsNaN(finalSize.Height))
            {
                return(base.ArrangeOverride(finalSize));
            }

            // Stop the animations and dispose the previous nodes
            // and their animations
            if (_isAnimationStarted)
            {
                for (var i = 0; i < _nodes.Count; i++)
                {
                    _nodes[i].StopAnimation(AnimatedProperty);
                    _animations[i].Dispose();
                    _animations[i] = null;
                    _nodes[i].Dispose();
                    _nodes[i] = null;
                }

                _container.StopAnimation(AnimatedProperty);
                _containerAnimation.Dispose();
                _containerAnimation = null;
                _container.Dispose();
                _container = null;

                _animations.Clear();
                _nodes.Clear();

                _isAnimationStarted = false;
            }

            // Validate MaxNodes and ActiveNodes
            if ((MaxNodes <= 0) || (ActiveNodes <= 0))
            {
                return(finalSize);
            }

            // Coerce ActiveNodes to MaxNodes if ActiveNodes > MaxNodes
            if (ActiveNodes > MaxNodes)
            {
                ActiveNodes = MaxNodes;
            }

            // Take the smallest of the width or height
            var sideLength = (float)Math.Min(finalSize.Width, finalSize.Height);

            // Size of the progress ring displayed
            _ringSize = new Vector2(sideLength, sideLength);
            var sideHalf = sideLength / 2f;

            // Radius of each node
            _nodeRadius = (float)NodeSizeFactor * sideHalf;
            // Size of each node
            _nodeSize = new Vector2(_nodeRadius * 2f, _nodeRadius * 2f);
            // Radius of the node
            _ringRadius = sideHalf - _nodeRadius;

            // Each animation will consist of '_maxFrameBlocks' number of
            // FrameBlocks. Each FrameBlock will consist of keyframes which allow
            // the element being animated to move to the next slot and wait
            // at that slot until all other elements have moved to their next slot.
            // Each FrameBlock (except the last one) will have '_maxFramesPerBlock'
            // number of keyframes. The last keyframe in the last FrameBlock
            // will always be (1f, "this.StartingValue + 360")

            // Total number of FrameBlocks in each animation
            _maxFrameBlocks = ActiveNodes;
            // Total keyframes in each FrameBlock
            _maxFramesPerBlock = ActiveNodes + 1;
            // Total keyframes in each animation
            _maxKeyFrames = _maxFrameBlocks * _maxFramesPerBlock;
            // Normalized Progress Key unit value for each keyframe
            _keyFrameSlice = 1f / _maxKeyFrames;

            // ========================================================================
            // NOTE:
            // gamma * maxNodes = 360
            // gamma = alpha + beta
            // beta = 2 * Asin(nodeRadius / ringRadius) * (180 / Math.PI)
            // invisibleNodes = MaxNodes - ActiveNodes
            // phi = (invisibleNodes * gamma)
            // theta = phi - beta
            // ========================================================================

            // gamma is the angle between adjacent nodes when maxNodes number of nodes are arranged in a circle
            _gamma = 360f / MaxNodes;
            // beta is the angle a node must travel after hitting the adjacent node
            _beta = 2f * (float)(Math.Asin(_nodeRadius / _ringRadius) * (180f / Math.PI));
            // alpha is the smallest angle a node must travel before hitting the adjacent node
            _alpha = _gamma - _beta;
            // phi is the angle occupied by (MaxNodes - ActiveNodes) number of nodes
            _phi = (MaxNodes - ActiveNodes + 1) * _gamma;
            // theta is the largest angle a node must travel before hitting the adjacent node
            _theta = _phi - _beta;

            // Create the Animations
            _animations = CreateAnimations();

            // Create the Container
            _container        = _compositor.CreateContainerVisual();
            _container.Size   = _ringSize;
            _container.Offset = new Vector3(((float)finalSize.Width - sideLength) / 2f,
                                            ((float)finalSize.Height - sideLength) / 2f,
                                            0f);
            _container.CenterPoint = new Vector3(_ringSize.X / 2f, _ringSize.Y / 2f, 0f);

            // Create the Nodes
            var offset      = new Vector3(_nodeRadius, _ringSize.Y / 2f, 0);
            var centerPoint = new Vector3(_ringSize.X / 2f - _nodeRadius, 0, 0);

            _nodes = new List <SpriteVisual>();
            var geometry = CanvasGeometry.CreateCircle(_generator.Device, new Vector2(_nodeRadius, _nodeRadius), _nodeRadius);
            // Create/Update the nodeMask
            var color = NodeColor;

            if (_nodeMask == null)
            {
                //Task.Run(async () =>
                //        {
                _nodeMask = _generator.CreateGeometrySurface(_nodeSize.ToSize(), geometry, color);
                //    })
                //.Wait();
            }
            else
            {
                //Task.Run(async () =>
                //        {
                _nodeMask.Redraw(_nodeSize.ToSize(), geometry, color);
                //    })
                //.Wait();
            }

            // Create the SurfaceBrush for the nodes
            var brush = _compositor.CreateSurfaceBrush(_nodeMask.Surface);

            var baseAngle = 0f;

            // Create the visuals for the nodes
            for (var i = 0; i < _maxFramesPerBlock; i++)
            {
                var node = _compositor.CreateSpriteVisual();
                node.Size                   = _nodeSize;
                node.AnchorPoint            = new Vector2(0.5f);
                node.Offset                 = offset;
                node.CenterPoint            = centerPoint;
                node.Brush                  = brush;
                node.RotationAngleInDegrees = baseAngle;
                if (i == 0)
                {
                    baseAngle += _phi;
                }
                else if (i == _maxFramesPerBlock - 2)
                {
                    baseAngle = -_beta;
                }
                else
                {
                    baseAngle += _gamma;
                }

                _nodes.Add(node);
                // Add the visual to the container
                _container.Children.InsertAtTop(node);
            }

            // Add the container to the Visual Tree
            ElementCompositionPreview.SetElementChildVisual(this, _container);

            // Start Node animations
            for (var i = 0; i < _maxFramesPerBlock; i++)
            {
                _nodes[i].StartAnimation(AnimatedProperty, _animations[i]);
            }

            // Start container animation
            _containerAnimation = _compositor.CreateScalarKeyFrameAnimation();
            _containerAnimation.InsertExpressionKeyFrame(1f, "this.StartingValue + 360f", _compositor.CreateLinearEasingFunction());
            _containerAnimation.Duration          = RingDuration;
            _containerAnimation.IterationBehavior = AnimationIterationBehavior.Forever;

            _container.StartAnimation(AnimatedProperty, _containerAnimation);

            _isAnimationStarted = true;

            return(finalSize);
        }
예제 #14
0
 public static CanvasGeometry GetDotGeometry(ICanvasResourceCreator resourceCreator, DotShape shape,
                                             Vector2 point, float dotWidth, float dotHeight)
 {
     return(CanvasGeometry.CreateCircle(resourceCreator, point, dotWidth / 2));
 }
예제 #15
0
        public void CreateLoadingWave(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args, Vector2 position, Color color)
        {
            if (rate >= 10)
            {
                percent++;
                rate = 0;
            }
            if (percent > 100)
            {
                percent = 0;
            }

            CanvasTextLayout textLayout = new CanvasTextLayout(sender, $"{percent}", new CanvasTextFormat()
            {
                FontSize = RadiusValue
            }, RadiusValue * 2, RadiusValue * 2);

            CanvasGeometry orignalText = CanvasGeometry.CreateText(textLayout);
            var            rectText    = orignalText.ComputeBounds();
            var            textOffsetX = (RadiusValue * 2 - textLayout.LayoutBoundsIncludingTrailingWhitespace.Width) / 2;
            var            textOffsetY = (RadiusValue * 2 - textLayout.LayoutBoundsIncludingTrailingWhitespace.Height) / 2;

            orignalText = orignalText.Transform(Matrix3x2.CreateTranslation((float)textOffsetX + position.X, (float)textOffsetY + position.Y));

            CanvasPathBuilder builder = new CanvasPathBuilder(sender);

            var offsetY = 2 * rate / 10 + percent * 2;

            builder.BeginFigure(0 + offsetX + position.X, RadiusValue * 2 - offsetY + position.Y);

            builder.AddCubicBezier(new Vector2(RadiusValue * 1 + offsetX + position.X, RadiusValue * 2 + RadiusValue / 3 - offsetY + position.Y), new Vector2(RadiusValue * 1 + offsetX + position.X, RadiusValue * 2 - RadiusValue / 3 - offsetY + position.Y), new Vector2(RadiusValue * 2 + offsetX + position.X, RadiusValue * 2 - offsetY + position.Y));

            builder.AddCubicBezier(new Vector2(RadiusValue * 3 + offsetX + position.X, RadiusValue * 2 + RadiusValue / 3 - offsetY + position.Y), new Vector2(RadiusValue * 3 + offsetX + position.X, RadiusValue * 2 - RadiusValue / 3 - offsetY + position.Y), new Vector2(RadiusValue * 4 + offsetX + position.X, RadiusValue * 2 - offsetY + position.Y));

            builder.AddLine(RadiusValue * 4 + offsetX + position.X, RadiusValue * 4 + position.Y);
            builder.AddLine(0 + offsetX + position.X, RadiusValue * 4 + position.Y);

            builder.EndFigure(CanvasFigureLoop.Closed);

            var wavePath   = CanvasGeometry.CreatePath(builder);
            var circlePath = CanvasGeometry.CreateCircle(sender, new Vector2(RadiusValue, RadiusValue), RadiusValue);

            var backgroundPath = circlePath.CombineWith(wavePath, Matrix3x2.Identity, CanvasGeometryCombine.Intersect);

            var topText   = orignalText.CombineWith(backgroundPath, Matrix3x2.Identity, CanvasGeometryCombine.Exclude);
            var drawnText = orignalText.CombineWith(backgroundPath, Matrix3x2.Identity, CanvasGeometryCombine.Intersect);


            args.DrawingSession.FillGeometry(backgroundPath, position, color);
            args.DrawingSession.FillGeometry(topText, color);
            args.DrawingSession.FillGeometry(drawnText, Colors.White);

            var borderCircle = CanvasGeometry.CreateCircle(sender, new Vector2(RadiusValue, RadiusValue), RadiusValue - 1);

            args.DrawingSession.DrawGeometry(borderCircle, position, color);

            offsetX--;
            if (offsetX <= -RadiusValue * 2)
            {
                offsetX = 0;
            }
            rate++;
        }
예제 #16
0
        private CanvasCachedGeometry CreateCachedGeometry(float scale, float thickness, float factor = 0.5f)
        {
            CanvasDevice device = CanvasDevice.GetSharedDevice();

            if (device == null)
            {
                return(null);
            }

            CanvasPathBuilder pathBuilder = new CanvasPathBuilder(device);

            pathBuilder.SetFilledRegionDetermination(CanvasFilledRegionDetermination.Winding);

            float maxThickness = thickness;
            float minThickness = thickness / 5;

            bool closedPath = false;

            int count = points.Count;

            for (int i = 0; i < count; i++)
            {
                // 끝점 2개가 완전히 일치하면 하나만 넣는다.
                if (i > 0 && i == count - 1 && (points[i].X == points[i - 1].X && points[i].Y == points[i - 1].Y))
                {
                    continue;
                }
                else
                {
                    float force = points[i].Force;
                    force = (force < 0) ? 0 : points[i].Force;
                    force = (force > 1.0f) ? 1.0f : points[i].Force;

                    // 점의 두께 차이가 최대 4배가 되도록 조정
                    //float normalForce = 0.2 + ( force * 0.6 );	// 0.2 ~ 0.8
                    midPoints.Add(points[i]);
                    //midPoints.Add(new Point(new Point(points[i].X, points[i].Y, force), scale));
                }
            }

            //if (points.Count > midPoints.Count)
            //    Debug.WriteLine("filtered : " + (points.Count - midPoints.Count));

            count = midPoints.Count;

            // 선 두께에 비해 가까운 점이나 라인상 거의 필요가 없다고 판단되는 점을 지우는 부분
            if (midPoints.Count > 2)
            {
                Simplify(midPoints, maxThickness);
            }

            //if (count > midPoints.Count)
            //    Debug.WriteLine("simplify : " + (count - midPoints.Count));

            count = midPoints.Count;
            // 처음과 끝에 펜 구동상 꼬리가 생기는 경우 꼬리를 판단해서 제거하는 부분
            // 꼬리는 없을수도 있다.
            // 미완성
            if (midPoints.Count > 2)
            {
                RemoveTail(midPoints, maxThickness);
            }

            //if (count > midPoints.Count)
            //    Debug.WriteLine("removeTail : " + (count - midPoints.Count));

            count = midPoints.Count;

            // 점 제거 로직 후 점이 하나만 남으면 원으로 그린다.
            // Neo Studio에서는 점이 하나일때 가까운 점을 하나 더 추가하여 2점 처리를 한다.
            if (count == 1)
            {
                float force = midPoints[0].Force < 0.3f ? 0.3f : midPoints[0].Force;
                //float r = maxThickness * force * 3.0f * 1.5f;
                float p = PenInkFactor * Pixel2DotScaleFactor * force * scale * maxThickness;
                using (var geom = CanvasGeometry.CreateCircle(device, midPoints[0].X, midPoints[0].Y, p / 2))
                {
                    return(CanvasCachedGeometry.CreateFill(geom));
                }
            }
            else
            {
                GetControlPoint(midPoints, midPoints.Count, closedPath, factor);
                GetSplitPoints(midPoints, 0.1f, 60);
                count = midPoints.Count;

                for (int i = 0; i < count; i++)
                {
                    float px = midPoints[i].OutX - midPoints[i].InX;
                    float py = midPoints[i].OutY - midPoints[i].InY;
                    float dp = midPoints[i].GetDistanceInOut();
                    float pp = maxThickness * midPoints[i].Force;

                    pp *= 1.5f;

                    if (pp < minThickness)
                    {
                        pp = minThickness;
                    }

                    // 첫점과 끝점 처리
                    if (i == 0)
                    {
                        px = midPoints[i + 1].X - midPoints[i].X;
                        py = midPoints[i + 1].Y - midPoints[i].Y;
                        dp = (float)Math.Sqrt(px * px + py * py);
                    }
                    else if (i == midPoints.Count - 1)
                    {
                        px = midPoints[i].X - midPoints[i - 1].X;
                        py = midPoints[i].Y - midPoints[i - 1].Y;
                        dp = (float)Math.Sqrt(px * px + py * py);
                    }

                    if (dp != 0)
                    {
                        rightPoints.Add(new DrawablePoint(midPoints[i].X - (py * pp / dp), midPoints[i].Y + (px * pp / dp), midPoints[i].Force));
                        leftPoints.Add(new DrawablePoint(midPoints[i].X + (py * pp / dp), midPoints[i].Y - (px * pp / dp), midPoints[i].Force));
                    }
                    else
                    {
                        rightPoints.Add(new DrawablePoint(midPoints[i].X, midPoints[i].Y, midPoints[i].Force));
                        leftPoints.Add(new DrawablePoint(midPoints[i].X, midPoints[i].Y, midPoints[i].Force));
                    }
                }

                GetControlPoint(leftPoints, leftPoints.Count, true, factor);
                GetControlPoint(rightPoints, rightPoints.Count, true, factor);

                foreach (var pt in leftPoints)
                {
                    pt.SetScale(scale / 56f);
                }

                foreach (var pt in rightPoints)
                {
                    pt.SetScale(scale / 56f);
                }

                DrawPath(pathBuilder, leftPoints, rightPoints);

                using (var geom = CanvasGeometry.CreatePath(pathBuilder))
                {
                    return(CanvasCachedGeometry.CreateFill(geom));
                }
            }
        }
예제 #17
0
        private CanvasCachedGeometry CreateCachedGeometryPreviousVersion(float scale, float thickness)
        {
            CanvasDevice device = CanvasDevice.GetSharedDevice();

            if (device == null)
            {
                return(null);
            }

            foreach (var pt in points)
            {
                midPoints.Add(new DrawablePoint(pt.X / 56f, pt.Y / 56f, pt.Force * pt.MaxForce));
            }

            var dots = midPoints;

            if (dots.Count <= 2)
            {
                float p = CalcForce(dots[0].Force, scale, thickness);

                if (dots.Count == 1) // 점찍기
                {
                    using (var geom = CanvasGeometry.CreateCircle(device, dots[0].X * scale, dots[0].Y * scale, p / 2))
                    {
                        return(CanvasCachedGeometry.CreateFill(geom));
                    }
                }
                else if (dots.Count == 2) // 선그리기
                {
                    float p2 = CalcForce(dots[0].Force, scale, thickness);

                    CanvasPathBuilder pathBuilder = new CanvasPathBuilder(device);
                    pathBuilder.SetFilledRegionDetermination(CanvasFilledRegionDetermination.Winding);
                    pathBuilder.BeginFigure(dots[0].X * scale, dots[0].Y * scale);
                    pathBuilder.AddLine(dots[1].X * scale, dots[1].Y * scale);
                    pathBuilder.EndFigure(CanvasFigureLoop.Open);
                    using (var geom = CanvasGeometry.CreatePath(pathBuilder))
                    {
                        return(CanvasCachedGeometry.CreateStroke(geom, (p + p2) / 2, GetStrokesStyle()));
                    }
                }
            }
            else
            {
                float x0, x1, x2, x3, y0, y1, y2, y3, p0, p1, p2, p3;
                float vx01, vy01, vx21, vy21;
                float norm;
                float n_x0, n_y0, n_x2, n_y2;

                x0 = dots[0].X * scale + 0.1f;
                y0 = dots[0].Y * scale;

                // TODO Change MaxForce
                //p0 = (float)dots[0].Force / 1024 * width;
                p0 = CalcForce(dots[0].Force, scale, thickness) / 2;

                x1 = dots[1].X * scale + 0.1f;
                y1 = dots[1].Y * scale;

                //p1 = (float)dots[1].Force / 1024 * width;
                p1 = CalcForce(dots[1].Force, scale, thickness) / 2;

                vx01 = x1 - x0;
                vy01 = y1 - y0;

                // instead of dividing tangent/norm by two, we multiply norm by 2
                norm = (float)Math.Sqrt(vx01 * vx01 + vy01 * vy01 + 0.0001f) * 2f;
                //vx01 = vx01 / norm * scaled_pen_thickness * p0;
                //vy01 = vy01 / norm * scaled_pen_thickness * p0;
                vx01 = vx01 / norm * p0;
                vy01 = vy01 / norm * p0;
                n_x0 = vy01;
                n_y0 = -vx01;

                CanvasPathBuilder pathBuilder = new CanvasPathBuilder(device);
                pathBuilder.SetFilledRegionDetermination(CanvasFilledRegionDetermination.Winding);

                int count = dots.Count;

                for (int i = 2; i < count; ++i)
                {
                    x3 = dots[i].X * scale + 0.1f;
                    y3 = dots[i].Y * scale;

                    //p3 = (float)dots[i].Force / 1024 * width;
                    //p3 = CalcForce(dots[i].Force, scale, thickness) / 2;
                    p3 = dots[i].Force;

                    x2 = (x1 + x3) / 2.0f;
                    y2 = (y1 + y3) / 2.0f;
                    p2 = (p1 + p3) / 2.0f;

                    vx21 = x1 - x2;
                    vy21 = y1 - y2;

                    norm = (float)System.Math.Sqrt(vx21 * vx21 + vy21 * vy21 + 0.0001f) * 2.0f;

                    vx21 = vx21 / norm * CalcForce(p2, scale, thickness);
                    vy21 = vy21 / norm * CalcForce(p2, scale, thickness);

                    n_x2 = -vy21;
                    n_y2 = vx21;

                    //pathBuilder = new CanvasPathBuilder(crt.Device);
                    pathBuilder.BeginFigure(x0 + n_x0, y0 + n_y0);
                    // The + boundary of the stroke
                    pathBuilder.AddCubicBezier(new Vector2(x1 + n_x0, y1 + n_y0), new Vector2(x1 + n_x2, y1 + n_y2), new Vector2(x2 + n_x2, y2 + n_y2));
                    // round out the cap
                    pathBuilder.AddCubicBezier(new Vector2(x2 + n_x2 - vx21, y2 + n_y2 - vy21), new Vector2(x2 - n_x2 - vx21, y2 - n_y2 - vy21), new Vector2(x2 - n_x2, y2 - n_y2));
                    // THe - boundary of the stroke
                    pathBuilder.AddCubicBezier(new Vector2(x1 - n_x2, y1 - n_y2), new Vector2(x1 - n_x0, y1 - n_y0), new Vector2(x0 - n_x0, y0 - n_y0));
                    // round out the other cap
                    pathBuilder.AddCubicBezier(new Vector2(x0 - n_x0 - vx01, y0 - n_y0 - vy01), new Vector2(x0 + n_x0 - vx01, y0 + n_y0 - vy01), new Vector2(x0 + n_x0, y0 + n_y0));
                    pathBuilder.EndFigure(CanvasFigureLoop.Open);

                    x0   = x2;
                    y0   = y2;
                    p0   = p2;
                    x1   = x3;
                    y1   = y3;
                    p1   = p3;
                    vx01 = -vx21;
                    vy01 = -vy21;
                    n_x0 = n_x2;
                    n_y0 = n_y2;
                }

                x2 = dots[count - 1].X * scale + 0.1f;
                y2 = dots[count - 1].Y * scale;
                p2 = dots[count - 1].Force;

                vx21 = x1 - x2;
                vy21 = y1 - y2;

                norm = (float)Math.Sqrt(vx21 * vx21 + vy21 * vy21 + 0.0001f) * 2f;

                vx21 = vx21 / norm * CalcForce(p2, scale, thickness);
                vy21 = vy21 / norm * CalcForce(p2, scale, thickness);

                n_x2 = -vy21;
                n_y2 = vx21;

                pathBuilder.BeginFigure(x0 + n_x0, y0 + n_y0);
                pathBuilder.AddCubicBezier(new Vector2(x1 + n_x0, y1 + n_y0), new Vector2(x1 + n_x2, y1 + n_y2), new Vector2(x2 + n_x2, y2 + n_y2));
                pathBuilder.AddCubicBezier(new Vector2(x2 + n_x2 - vx21, y2 + n_y2 - vy21), new Vector2(x2 - n_x2 - vx21, y2 - n_y2 - vy21), new Vector2(x2 - n_x2, y2 - n_y2));
                pathBuilder.AddCubicBezier(new Vector2(x1 - n_x2, y1 - n_y2), new Vector2(x1 - n_x0, y1 - n_y0), new Vector2(x0 - n_x0, y0 - n_y0));
                pathBuilder.AddCubicBezier(new Vector2(x0 - n_x0 - vx01, y0 - n_y0 - vy01), new Vector2(x0 + n_x0 - vx01, y0 + n_y0 - vy01), new Vector2(x0 + n_x0, y0 + n_y0));
                pathBuilder.EndFigure(CanvasFigureLoop.Open);

                using (var geom = CanvasGeometry.CreatePath(pathBuilder))
                {
                    return(CanvasCachedGeometry.CreateFill(geom));
                }
            }

            return(null);
        }