locked
How to draw the curve for Implement the signature?

    Question

  • How to draw the curve for Implement the signature?
    Tuesday, August 6, 2013 7:19 AM

All replies

  • Tuesday, August 6, 2013 4:50 PM
    Owner
  • the sample use directX;

    my app is a xaml and C++ app;

    OnPointerPressed:

    m_LinesStartPoint = e->Position;

    IsDraw=true;

    OnPointerMoved:

    if(IsDraw)

    {

       Windows::UI::Input::PointerPoint^ pointerPoint = e->GetCurrentPoint( (*IterRectImage).m_SignPageShow);
       Windows::Foundation::Point m_LinesEndPoint;
        m_LinesEndPoint.X =pointerPoint->Position.X;// pointerPoint->Position.X;
        m_LinesEndPoint.Y =pointerPoint->Position.Y;// pointerPoint->Position.Y;
       
        Path^ path = ref new Windows::UI::Xaml::Shapes::Path() ;
        path->Stroke = ref new Windows::UI::Xaml::Media::SolidColorBrush(Windows::UI::Colors::Blue);
        path->StrokeThickness=2; 
        BezierSegment^ bezier = ref  new Windows::UI::Xaml::Media::BezierSegment();
        bezier->Point1 =m_LinesEndPoint;
        bezier->Point2 =m_LinesEndPoint;
        bezier->Point3 =m_LinesEndPoint;
        PathFigure^ figure = ref new PathFigure();   
        figure->StartPoint= m_LinesStartPoint ;
        figure->Segments->Append(bezier);
        PathGeometry^ geometry = ref new Windows::UI::Xaml::Media::PathGeometry();
        geometry->Figures->Append(figure);
        path->Data = geometry;
        mycanvas->Children->Append(path); 
        m_LinesStartPoint.X = m_LinesEndPoint.X;
        m_LinesStartPoint.Y = m_LinesEndPoint.Y;   

    }

    OnPointerReleased:

    IsDraw=false;

    use this for signature,but the curve is intermittented ,why? what to do for  the curve  continuous and smooth ?

    Wednesday, August 7, 2013 9:35 AM
  • You can do the same thing as the sample does to capture the ink, but display the InkStrokes in Xaml Path elements.

    I'm not sure what you mean by "the curve is intermittented", but If you track the PointerMove messages yourself you may need to implement your own smoothing.

    --Rob

    Friday, August 9, 2013 11:39 PM
    Owner
  • how to display the InkStrokes in Xaml Path elements?

    in the sample:

    #pragma endregion
    
    #pragma region Bezier rendering
    
    // convert bezier control points in each segment to a bezier curve in the path geometry
    void simpleInk::ConvertStrokeToGeometry(_In_ Windows::UI::Input::Inking::InkStroke^ stroke, _Outptr_ ID2D1PathGeometry** geometry)
    {
        // create a geometry path
        DX::ThrowIfFailed(m_d2dFactory->CreatePathGeometry(geometry));
    
        // create and initialize a geometry sink
        Microsoft::WRL::ComPtr<ID2D1GeometrySink> sink;
        DX::ThrowIfFailed((*geometry)->Open(&sink));
        sink->SetSegmentFlags(D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN);
        sink->SetFillMode(D2D1_FILL_MODE_ALTERNATE);
    
        // obtain rendering segments for this stroke
        Windows::Foundation::Collections::IVectorView<Windows::UI::Input::Inking::InkStrokeRenderingSegment^>^ renderingSegments = stroke->GetRenderingSegments();
    
        // obtain first rendering segment, set as a starting point
        Windows::UI::Input::Inking::InkStrokeRenderingSegment^ firstSegment = renderingSegments->GetAt(0);
        Windows::Foundation::Point first = firstSegment->Position;
        sink->BeginFigure(D2D1::Point2F(first.X, first.Y), D2D1_FIGURE_BEGIN_FILLED);
    
        // process all remaining rendering segments, add bezier segment to the geometry path sink
        for (unsigned int j = 1; j < renderingSegments->Size; j++)
        {
            // obtain j-th rendering segment for the given stroke
            Windows::UI::Input::Inking::InkStrokeRenderingSegment^ renderingSegment = renderingSegments->GetAt(j);
    
            // add bezier segment to the geometry path sink
            sink->AddBezier(
                D2D1::BezierSegment(
                    D2D1::Point2F(renderingSegment->BezierControlPoint1.X, renderingSegment->BezierControlPoint1.Y),
                    D2D1::Point2F(renderingSegment->BezierControlPoint2.X, renderingSegment->BezierControlPoint2.Y),
                    D2D1::Point2F(renderingSegment->Position.X, renderingSegment->Position.Y)
                    )
                );
        }
    
        // done with given stroke, end and close geometry sink
        // sink will be automatically released as it is a smart pointer
        sink->EndFigure(D2D1_FIGURE_END_OPEN);
        DX::ThrowIfFailed(sink->Close());
    }
    
    // creates Bezier render, called by Render()
    void simpleInk::BezierRender()
    {
        // render all strokes
        Windows::Foundation::Collections::IVectorView<Windows::UI::Input::Inking::InkStroke^>^ inkStrokes = _strokeContainer->GetStrokes();
        for (unsigned int i = 0; i < inkStrokes->Size; i++)
        {
            // obtain the stroke
            Windows::UI::Input::Inking::InkStroke^ stroke = inkStrokes->GetAt(i);
    
            // convert stroke to geometry
            // geometry is a smart pointer and it is released right after it is used
            // for performance reasons one may consider storing geometry paths instead of auto-releasing them once they are used
            Microsoft::WRL::ComPtr<ID2D1PathGeometry> strokeGeometry;
            ConvertStrokeToGeometry(stroke, &strokeGeometry);
    
            // stroke's width and color are retrieved from the stroke's drawing attributes
            float width = stroke->DrawingAttributes->Size.Width;
            // create brush from current stroke
            Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> strokeBrush;
            CreateBrush(m_d2dContext.Get(), stroke->DrawingAttributes->Color, &strokeBrush);
            
            // render stroke geometry
            // if stroke is selected, we render its contour with the stroke's color and we fill it with white
            if (stroke->Selected)
            {
                m_d2dContext->DrawGeometry(strokeGeometry.Get(), strokeBrush.Get(), width + 2, _inkStyle.Get());
                m_d2dContext->DrawGeometry(strokeGeometry.Get(), _backgroundBrush.Get(), width, _inkStyle.Get());
            }
            else
            {
                m_d2dContext->DrawGeometry(strokeGeometry.Get(), strokeBrush.Get(), width, _inkStyle.Get());
            }        
        }
    }

     how to Implement these two function in Xaml ??

    now I only can do draw lines in Xaml ,but the showing effect is not  good.

    Monday, August 12, 2013 4:30 AM
  • You can do the same thing as the sample does to capture the ink, but display the InkStrokes in Xaml Path elements.

    I'm not sure what you mean by "the curve is intermittented", but If you track the PointerMove messages yourself you may need to implement your own smoothing.

    --Rob


    I track the PointerMove messages ,how to  implement the curve‘s  smoothing?
    Tuesday, August 13, 2013 10:56 AM
  • How to Implement the signature   on   touch device  in   Input: Simplified ink sample (Windows 8)

     

       public void InkCanvas_PointerPressed(object sender, PointerRoutedEventArgs e)        {            // Get information about the pointer location.            PointerPoint pt = e.GetCurrentPoint(panelcanvas);            _previousContactPt = pt.Position;            // Accept input only from a pen or mouse with the left button pressed.             PointerDeviceType pointerDevType = e.Pointer.PointerDeviceType;            if (pointerDevType == PointerDeviceType.Pen ||                    pointerDevType == PointerDeviceType.Mouse &&                    pt.Properties.IsLeftButtonPressed)            {                // Pass the pointer information to the InkManager.                _inkManager.ProcessPointerDown(pt);                _penID = pt.PointerId;                e.Handled = true;            }            else if (pointerDevType == PointerDeviceType.Touch)            {                // Process touch input            }
    how to  Implement  // Process touch input

    Wednesday, August 14, 2013 2:16 AM
  • CurrentContactPoint = e->GetCurrentPoint((*IterRectImage).m_SignPageShow)->Position;
    							X1 = PreviousContactPoint.X;
    							Y1 = PreviousContactPoint.Y;
    							X2 = CurrentContactPoint.X;
    							Y2 = CurrentContactPoint.Y;
    								
    							   if (sqrt(pow((X2 - X1), 2) +pow((Y2 - Y1), 2)) > 4.0)
    								{
    						
    									Line^ line = ref new Windows::UI::Xaml::Shapes::Line();								
    									line->X1 = X1;
    									line->Y1 = Y1;
    									line->X2 = X2;
    									line->Y2 = Y2;
    									line->StrokeThickness = strokethickness;
    									line->Stroke = ref new SolidColorBrush(color);
    									line->StrokeStartLineCap = Windows::UI::Xaml::Media::PenLineCap::Round;
    									line->StrokeEndLineCap = Windows::UI::Xaml::Media::PenLineCap::Round;								
    									line->StrokeDashCap = Windows::UI::Xaml::Media::PenLineCap::Round;
    					                line->StrokeLineJoin = Windows::UI::Xaml::Media::PenLineJoin::Round;
    									line->StrokeMiterLimit =true;
    									PreviousContactPoint = CurrentContactPoint;
    									Canvas->Children->Append(line);
    									MyInkManager->ProcessPointerUpdate(e->GetCurrentPoint(Canvas);
    on the touchScreen the line is not smooth ,and is bending?how to solve this problem ?
    Friday, August 16, 2013 10:23 AM
  • Please don't post multiple threads on the same question. As suggested in your previous thread, the InkManagercwill provide smoothing for you. If you don't want to use the InkManager you will need to come up with your own smoothing algorithm. Using a single Path object with several BezierSegments will be a start, but you may need to process the raw pints read in. Search for algorithms for fitting a curve to a collection of points.

    --Rob

    Friday, August 16, 2013 2:07 PM
    Owner