Oppure

Loading
01/03 10:11
nightwolf
buon giorno a tutti, sto continuando il mio progetto riguardante uno stereo interattivo, dopo aver completato la parte audio, stazione radio e musica, adesso mi è venuto il pallino di avere una bussola in macchina, vedendola nella macchina di mia moglie, ho detto perchè non averla anchio.
tramite arduino e un gps posso inviare al mio progetto la direzione, (nord, sud, est, west), adesso, il problema sta nel disegnare la bussola e cioè nel far girare la bussola di un gradoalla volta in base alla direzione presente nella label. mi spiego meglio,
se nella label1 c'è scritto "nord" la bussola devo girare dal punto dove si trova fino ad arrivare al grado "0" o "360", cosi x il resto delle coordinate, ho visto alcuni esempi, ma fanno girare l immagine con un timer all' infinito. come posso fare? credo che bisogna avere un timer sempre attivo, perchè ogni qualvolta che la label cambia text questo devo far ruotare l immagine, ma di più non so.
grazie mille
questo è l immagine che intendo usare
aaa
01/03 15:22
Thejuster
Partiamo dal timer.

Il timer è un elemento indispensabile, perché serve ad invalidare o meglio a ridisegnare la scena.
insomma il refresh per ridisegnare tutto.

per l'indicatore si usa da sempre la semplice formula del PI.

rotazioneGradi = 120 Esempio.

Per essere sicuri che i gradi siano da 0 ad un max di 360
rotazioneGradi %= 360;

angoloRadiante = rotazioneGradi * Math.PI / 180;


In questo modo, hai ottenuto l'angolo dei gradi in radianti.

Per il comparto grafico, dai un occhiata qui.

pierotofy.it/pages/sorgenti/dettagli/19517-Orologio_analogico_fotorealistico/

apri il sorgente e cerca di capire come è strutturato il funzionamento dell'orologio.
Applicando la stessa teoria alla tua bussola.

Se ti serve anche una buona libreria grafica e performante, ti consiglio il mio progetto.

pierotofy.it/pages/projects/…

puoi sfruttare tutta la GDI in seguito direttamente nel void Draw.
La differenza e che non hai bisogno di nessun timer, e tutto già pre-impostato,
ed hai la possibilità di avere un zoom o una telecamera 2d.








mire.forumfree.it/ - Mire Engine
C# UI Designer
01/03 15:48
Carlo
Per il timer sei a posto, Thejuster è stato chiaro.

Ti propongo un codice che al variare del contenuto in gradi di una label ruota l'immagine di conseguenza:

1) ho inserito una scrollbar che simula la variazione del valore in gradi nella label (entrambi creati in runtime).
2) ho ridimensionato l'immagine e ritagliata circolare in modo che possa essere sovrapposta a qualsiasi altro disegno (allegata).
3) codice in C#

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace Ruota_Immagine
{
    public partial class Form1 : Form
    {
        Image bussola = new Bitmap("bussola.png"); // bmp in ram dal file originale, deve esistere nella cartella dell'eseguibile
        Label lb = new Label(); // label con il valore di rotazione
        HScrollBar hsb = new HScrollBar(); // simulazione dato di rotazione
        public Form1()
        {
            InitializeComponent();
            this.BackgroundImageLayout = ImageLayout.Zoom; // adatta l'immagine al ridimensionamento
            this.DoubleBuffered = true; // elimina sfarfallio
            hsb.Left = lb.Width; // posizione della scrollbar
            hsb.Width =  this.ClientSize.Width - lb.Width; // larghezza della scrollbar
            hsb.Maximum = 370; // valore massimo scrollbar
            this.Controls.Add(lb); // label nel form
            this.Controls.Add(hsb); // scrollbar nel form
            lb.TextChanged += Lb_TextChanged; // evento cambio testo nella label
            hsb.Scroll += Hsb_Scroll; // evento cambiovalore nella scrollbar
            lb.Text = "000";
            Lb_TextChanged(lb, new EventArgs()); // primo disegno
        }

        private void Hsb_Scroll(object sender, EventArgs e)
        {
            lb.Text = hsb.Value.ToString("000"); // cambia il valore nella label (simula il tuo valore)
        }

        private void Lb_TextChanged(object sender, EventArgs e) // al cambio del valore
        {
            int valoreGradi = Convert.ToUInt16(lb.Text); // valore in gradi
            Image rot0 = (Image)bussola.Clone(); // partenza sempre dall'originale a zero gradi
            Graphics g = Graphics.FromImage(rot0); // layer grafico di lavoro
            // centro immagine
            int centerX = rot0.Width / 2;
            int centerY = rot0.Height / 2;
            // Crea una matrice di trasformazione per ruotare l'immagine
            Matrix matrix = new Matrix();
            matrix.Translate(centerX, centerY); // coordinate di riferimento al centro
            matrix.Rotate(valoreGradi); // rotazione
            // Applica la trasformazione all'immagine
            g.Transform = matrix;
            // Disegna l'immagine ruotata nella bitmap centrata
            g.DrawImage(rot0, -centerX, -centerY);
            this.BackgroundImage = rot0; // la bitmap nel form
            this.Refresh(); // aggiorna il form
        }
    }
}


Codice commentato ma se vuoi più info chiedi

Invece non ho compreso la richiesta: ...la direzione, (nord, sud, est, west)

Ultima modifica effettuata da Carlo 01/03 16:33
in programmazione tutto è permesso
01/03 23:30
nightwolf
la mia richiesta è che se il testo nella label1 è "NORD", la bussola devrebbe indicare in nord, cosi come se il testo della label1 è sud la bussola dovrebbe indicare il sud, ma non semplicemente cambiando imagine, perchè fin li, riesco anchio, ma vedendola muovere o solamente verso destra, o solamente verso sinistra, di grado in grado, come una bussola vera.
aaa
02/03 9:09
Thejuster
Solitamente non regalo sorgenti.
Ma visto il mal tempo, non avevo nulla da fare, ed eccomi qui.

Non lo faccio non per cattiveria, ma perché lo scopo del forum e quello di aiutare, consigliare ed imparare
non di regalare sorgenti pronti.

Non è rivolto semplicemente a te nightwolf ma alla community in generale.

Ho fatto questo piccolo esempio suppongo che sia questo quello che cerchi.
con tanto di animaizone.

Spostando la trackbar ed assegnando un nuovo valore, la lancetta ruoterà un pò alla volta fino a raggiungere il valore.



Edit:
screenshoot

i.ibb.co/fSPwn4X/…

L'angolo parte da 0, ovvero W 270
basta modificare la variabile

angoloattuale = 90.0; per ottenere come punto di partenza lo 0

quindi ad esempio se la bussola dovrebbe puntare a Nord 5 gradi


addizione = 90.0;

angoloattuale = 5.0 + addizione;
Ultima modifica effettuata da Thejuster 02/03 9:34
mire.forumfree.it/ - Mire Engine
C# UI Designer
02/03 11:56
Carlo
Mi sembra che oggi ti vada bene, Thejuster ti ha regalato la bussola con l'ago.

Io ti regalo la bussola con il quadrante che ruota (allegato progetto).
L'esempio che ti avevo postato andava integrato con la richiesta nord, est, sud, west
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace Ruota_Immagine
{
    public partial class Form1 : Form
    {
        Image bussola = new Bitmap("bussola.png"); // bmp in ram dal file originale, deve esistere nella cartelle dell'eseguibile
        int destinazione;
        int avanzamento;
        int direzione;
        public Form1()
        {
            InitializeComponent();
            this.BackgroundImageLayout = ImageLayout.Zoom; // adatta l'immagine al ridimensionamento
            this.DoubleBuffered = true; // elimina sfarfallio
            Lb_TextChanged(lb, new EventArgs()); // primo disegno
        }

        private void Lb_TextChanged(object sender, EventArgs e) // al cambio del valore
        {
            int valoreGradi = Convert.ToUInt16(lb.Text); // valore in gradi
            Image rot0 = (Image)bussola.Clone(); // partenza sempre dall'originale a zero gradi
            Graphics g = Graphics.FromImage(rot0); // layer grafico di lavoro
            // centro immagine
            int centerX = rot0.Width / 2;
            int centerY = rot0.Height / 2;
            // Crea una matrice di trasformazione per ruotare l'immagine
            Matrix matrix = new Matrix();
            matrix.Translate(centerX, centerY); // coordinate di riferimento al centro
            matrix.Rotate(valoreGradi); // rotazione
            // Applica la trasformazione all'immagine
            g.Transform = matrix;
            // Disegna l'immagine ruotata nella bitmap centrata
            g.DrawImage(rot0, -centerX, -centerY );
            this.BackgroundImage = rot0; // la bitmap nel form
            this.Refresh(); // aggiorna il form
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            avanzamento += direzione;
            lb.Text = avanzamento.ToString("000");
            if (avanzamento == destinazione) timer1.Enabled = false;
        }

        private void butNord_Click(object sender, EventArgs e)
        {
            destinazione = 0;
            // esce se già in posizione
            if (destinazione == avanzamento || avanzamento == 360) return;
            // sceglie la direzione di rotazione
            if (avanzamento > 180)
            {
                direzione = 2;
                destinazione = 360;
            }
            else
            {
                direzione = -2;
                destinazione = 0;
            }
            timer1.Enabled = true;
        }

        private void butEst_Click(object sender, EventArgs e)
        {
            destinazione = 90;
            // esce se già in posizione
            if (destinazione == avanzamento) return;
            // normalizza
            if (avanzamento == 360) avanzamento = 0;
            // sceglie la direzione di rotazione
            if (avanzamento > 90) direzione = -2; else direzione = 2;
            timer1.Enabled = true;
        }

        private void butSud_Click(object sender, EventArgs e)
        {
            destinazione = 180;
            // esce se già in posizione
            if (destinazione == avanzamento) return;
            // sceglie la direzione di rotazione
            if (avanzamento > 180) direzione = -2; else direzione = 2;
            timer1.Enabled = true;
        }

        private void butWest_Click(object sender, EventArgs e)
        {
            destinazione = 270;
            // esce se già in posizione
            if (destinazione == avanzamento) return;
            // normalizza
            if (avanzamento == 0) avanzamento = 360;
            // sceglie la direzione di rotazione
            if (avanzamento > 180) direzione = -2; else direzione = 2;
            timer1.Enabled = true;
        }
    }
}

Come vedi il codice è lo stesso di prima solo che i valori vengono aggiornati con un timer e vanno nel punto cardinale scelto.

Mi aspetto che tu ci esponga i tuoi dubbi, gli esempi sono per iniziare...
in programmazione tutto è permesso
02/03 12:16
nightwolf
grazie mille, questa mattina avevo gia iniziato a scrivere questo codice
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace bussola_c
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        int cx = 280, cy = 280, rx = 400, ry = 400;

        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Start();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            angle += 2;
            Invalidate();

        }

        float angle;
        Bitmap image = Properties.Resources.bussola;
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
                
            g.RotateTransform(angle, System.Drawing.Drawing2D.MatrixOrder.Append);
            g.TranslateTransform(cx, cy, System.Drawing.Drawing2D.MatrixOrder.Append);
            g.DrawImage(image, -rx / 2, -ry / 2, rx, ry);
        }
    }
}


e premendo il pulsante start, tutto funzionava, era solo da capire come far girare la bussola se si indicava nord, sud, est o west.
ho provato a convertire il codice in vb.net ma mi dava errore in g.DrawImage(image, -rx / 2, -ry / 2, rx, ry), e non capivo dove era lo sbaglio, stavo cercando in rete, prima di leggere i vostri esempi.
aaa
02/03 13:39
Carlo
Se ti trovi meglio con VB.Net

Ecco il codice (allegato anche progetto):

Imports System.Drawing.Drawing2D

Public Class Form1

    Private bussola As Image = New Bitmap("bussola.png") ' bmp in ram dal file originale, deve esistere nella cartelle dell'eseguibile
    Private destinazione As Integer
    Private avanzamento As Integer
    Private direzione As Integer

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        rotate(0) ' primo disegno
    End Sub

    Private Sub rotate(ByVal valoreGradi As Integer) ' aggiorna rotazione
        Dim rot0 As Image = DirectCast(bussola.Clone(), Image) ' partenza sempre dall'originale a zero gradi
        Dim g As Graphics = Graphics.FromImage(rot0) ' layer grafico di lavoro
        ' centro immagine
        Dim centerX As Integer = rot0.Width \ 2
        Dim centerY As Integer = rot0.Height \ 2
        ' Crea una matrice di trasformazione per ruotare l'immagine
        Dim matrix As New Matrix()
        matrix.Translate(centerX, centerY) ' coordinate di riferimento al centro
        matrix.Rotate(avanzamento) ' rotazione
        ' Applica la trasformazione all'immagine
        g.Transform = matrix
        ' Disegna l'immagine ruotata nella bitmap centrata
        g.DrawImage(rot0, -centerX, -centerY)
        Me.BackgroundImage = rot0 ' la bitmap nel form
        Me.Refresh() ' aggiorna il form
    End Sub

    Private Sub timer1_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles timer1.Tick
        avanzamento += direzione
        avanzamento = avanzamento Mod 360 ' azzera a 360°
        rotate(avanzamento)
        lb1.Text = avanzamento.ToString("000°")
        Dim west As Integer = (avanzamento + 180) Mod 360 ' azzera a 360°
        lb2.Text = west.ToString("000°")
        If avanzamento = destinazione Then
            timer1.Enabled = False
        End If
    End Sub

    Private Sub butNord_Click(ByVal sender As Object, ByVal e As EventArgs) Handles butNord.Click
        ' esce se già in posizione
        If avanzamento = 0 Then Exit Sub
        destinazione = 0
        ' sceglie la direzione di rotazione
        If avanzamento < 180 Then direzione = -2 Else direzione = 2
        timer1.Enabled = True
    End Sub

    Private Sub butEst_Click(ByVal sender As Object, ByVal e As EventArgs) Handles butEst.Click
        ' esce se già in posizione
        If avanzamento = 90 Then Exit Sub
        destinazione = 90
        ' sceglie la direzione di rotazione
        If avanzamento > 90 Then direzione = -2 Else direzione = 2
        timer1.Enabled = True
    End Sub

    Private Sub butSud_Click(ByVal sender As Object, ByVal e As EventArgs) Handles butSud.Click
        ' esce se già in posizione
        If avanzamento = 180 Then Exit Sub
        destinazione = 180
        ' sceglie la direzione di rotazione
        If avanzamento > 180 Then direzione = -2 Else direzione = 2
        timer1.Enabled = True
    End Sub

    Private Sub butWest_Click(ByVal sender As Object, ByVal e As EventArgs) Handles butWest.Click
        ' esce se già in posizione
        If avanzamento = 270 Then Exit Sub
        destinazione = 270
        ' normalizza
        If avanzamento = 0 Then avanzamento = 360
        ' sceglie la direzione di rotazione
        If avanzamento > 180 Then direzione = -2 Else direzione = 2
        timer1.Enabled = True
    End Sub

End Class


Come prima, questa è la partenza.
Se ti piace programmare non ti accontentare di copiare codice, approfitta di chi ti può spiegare passo passo i perché
Ultima modifica effettuata da Carlo 02/03 13:42
in programmazione tutto è permesso