Condividi tramite


Esempio di cancellazione dell'input penna

Questa applicazione si basa sull'esempio di esempio di raccolta input penna illustrando l'eliminazione dei tratti penna. L'esempio fornisce all'utente un menu che dispone di quattro modalità da scegliere: abilitata per l'input penna, cancellazione in cusp, cancellazione di intersezioni e tratti di cancellazione.

In modalità penna abilitata, l'oggetto InkCollector raccoglie l'input penna come illustrato nell'esempio di raccolta input penna.

In modalità di cancellazione, i segmenti di tratti penna esistenti che l'utente tocca con il cursore vengono cancellati. Inoltre, i cusps o gli intersezioni possono essere contrassegnati con un cerchio rosso.

Le parti più interessanti di questo esempio si trovano nel InkErase gestore eventi del OnPaint modulo e nelle funzioni di cancellazione chiamate dal gestore eventi del OnMouseMove modulo.

Circling the Cusps and Intersezioni

Il gestore eventi del OnPaint modulo disegna prima i tratti e, a seconda della modalità applicazione, può trovare e contrassegnare tutti i cusps o intersezioni con un piccolo cerchio rosso. Una cuspide contrassegna il punto in cui un tratto cambia direzione bruscamente. Un'intersezione contrassegna un punto in cui un tratto si interseca con se stesso o un altro tratto.

L'evento Paint si verifica ogni volta che viene ridisegnato un controllo.

Nota

L'esempio forza il modulo a ridisegnarsi ogni volta che un tratto viene cancellato o quando la modalità applicazione viene modificata, usando il metodo Refresh del modulo.

 

private void InkErase_OnPaint(object sender, PaintEventArgs e)
{
    Strokes strokesToPaint = myInkCollector.Ink.Strokes;

    myInkCollector.Renderer.Draw(e.Graphics, strokesToPaint);

    switch (mode)
    {
        case ApplicationMode.CuspErase:
            PaintCusps(e.Graphics, strokesToPaint);
            break;
        case ApplicationMode.IntersectErase:
            PaintIntersections(e.Graphics, strokesToPaint);
            break;
    }
}

In PaintCusps, il codice esegue l'iterazione di ogni cuspide in ogni tratto e disegna un cerchio rosso intorno a esso. La proprietà PolylineCusps del tratto restituisce gli indici dei punti all'interno di un stoke corrispondente a cusps. Si noti anche il metodo InkSpaceToPixel dell'oggetto Renderer, che converte il punto in coordinate pertinenti al metodo DrawEllipse.

private void PaintCusps(Graphics g, Strokes strokesToPaint)
{
    foreach (Stroke currentStroke in strokesToPaint)
    {
        int[] cusps = currentStroke.PolylineCusps;

        foreach (int i in cusps)
        {
            Point pt = currentStroke.GetPoint(i);

            // Convert the X, Y position to Window based pixel coordinates
            myInkCollector.Renderer.InkSpaceToPixel(g, ref pt);

            // Draw a red circle as the cusp position
            g.DrawEllipse(Pens.Red, pt.X-3, pt.Y-3, 6, 6);
        }
    }
}

In PaintIntersections, il codice esegue l'iterazione di ogni tratto per trovare le sue intersezioni con l'intero set di tratti. Si noti che il metodo FindIntersections del tratto viene passato un insieme Strokes e restituisce una matrice di valori di indice a virgola mobile che rappresentano gli intersezioni. Il codice calcola quindi una coordinata X-Y per ogni intersezione e disegna un cerchio rosso intorno a esso.

private void PaintIntersections(Graphics g, Strokes strokesToPaint)
{
    foreach (Stroke currentStroke in strokesToPaint)
    {
        float[] intersections =            currentStroke.FindIntersections(strokesToPaint);
    }
}

Gestione di una penna con due estremità

Tre gestori eventi sono definiti per l'oggetto InkCollector per gli eventi CursorDown, NewPackets e Stroke . Ogni gestore eventi controlla la proprietà Inverted dell'oggetto Cursor per verificare quale fine della penna viene usata. Quando la penna viene invertita:

  • Il myInkCollector_CursorDown metodo rende trasparente il tratto.
  • Il myInkCollector_NewPackets metodo cancella i tratti.
  • Il myInkCollector_Stroke metodo annulla l'evento. Gli eventi NewPackets vengono generati prima dell'evento Stroke .

Rilevamento del cursore

Se l'utente usa una penna o un mouse, vengono generati eventi MouseMove . Il gestore eventi MouseMove controlla prima di tutto se la modalità corrente è una modalità di cancellazione e se viene premuto un pulsante del mouse e ignora l'evento se questi stati non sono presenti. Il gestore eventi converte quindi le coordinate pixel per il cursore in coordinate dello spazio penna usando il metodo PixelToInkSpace dell'oggetto Renderer e chiama uno dei metodi di cancellazione del codice a seconda della modalità di cancellazione corrente.

Elimina tratti

Il EraseStrokes metodo accetta la posizione del cursore nello spazio penna e genera una raccolta di tratti che si trovano all'interno HitTestRadius di unità. Il currentStroke parametro specifica un oggetto Stroke che non deve essere eliminato. L'insieme di tratti viene quindi eliminato dall'agente di raccolta e il modulo viene ridisegnato.

private void EraseStrokes(Point pt, Stroke currentStroke)
{
    Strokes strokesHit = myInkCollector.Ink.HitTest(pt, HitTestRadius);

    if (null!=currentStroke && strokesHit.Contains(currentStroke))
    {
        strokesHit.Remove(currentStroke);
    }

    myInkCollector.Ink.DeleteStrokes(strokesHit);

    if (strokesHit.Count > 0)
    {
        this.Refresh();
    }
}

Cancellazione in intersezioni

Il EraseAtIntersections metodo esegue l'iterazione di ogni tratto che rientra nel raggio di test e genera una matrice di intersezioni tra tale tratto e tutti gli altri tratti della raccolta. Se non vengono trovati intersezioni, l'intero tratto viene eliminato; in caso contrario, il punto più vicino del tratto al punto di test si trova e da questo, le intersezioni su entrambi i lati del punto si trovano, descrivendo il segmento da rimuovere.

Il metodo Split dell'oggetto Stroke viene usato per separare il segmento dal resto del tratto e quindi il segmento viene eliminato, lasciando invariato il resto del tratto. Come in EraseStrokes, il modulo viene ridisegnato prima che il metodo restituisca.

private void EraseAtIntersections(Point pt)
{
    Strokes strokesHit = myInkCollector.Ink.HitTest(pt, HitTestRadius);

    foreach (Stroke currentStroke in strokesHit)
    {
        float[] intersections = currentStroke.FindIntersections(myInkCollector.Ink.Strokes);
        ...
        float findex = currentStroke.NearestPoint(pt);
        ...
        strokeToDelete = currentStroke.Split(intersections[i]);
        ...
    }
    ...
}

Cancellazione in Cusps

Per ogni tratto che rientra nel raggio di test, il EraseAtCusps metodo recupera la matrice di cusps dal metodo PolylineCusps dell'oggetto Stroke. Ogni fine del tratto è anche una cuspide, quindi se il tratto ha solo due cusps, l'intero tratto viene eliminato; in caso contrario, il punto più vicino del tratto al punto di test si trova e da questo, le intersezioni su entrambi i lati del punto si trovano, descrivendo il segmento da rimuovere.

Il metodo Split dell'oggetto Stroke viene usato per separare il segmento dal resto del tratto e quindi il segmento viene eliminato, lasciando invariato il resto del tratto. Come in EraseStrokes, il modulo viene ridisegnato prima che il metodo restituisca.

private void EraseAtCusps(Point pt)
{
    ...
    strokesHit = myInkCollector.Ink.HitTest(pt, HitTestRadius);
    
    foreach (Stroke currentStroke in strokesHit)
    {
        int[] cusps = currentStroke.PolylineCusps;
        ...
        float findex = currentStroke.NearestPoint(pt);
        ...
        strokeToDelete = currentStroke.Split(cusps[i]); 
        myInkCollector.Ink.DeleteStroke(strokeToDelete);
        ...
    }
    ...
}

Chiusura del modulo

Il metodo Dispose del modulo elimina l'oggetto InkCollector , myInkCollector.