Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: VB6: Piirtäminen Visual Basicilla

Sivun loppuun

Veikko [25.07.2007 08:02:07]

#

Moi

Olen nyt piirtämässä visual basic 6:lla kappaletta. Kappale koostuu osista, jotka ovat kiinni toisissaan, mutta ne piirretään eri aikaan. Eli esimerkiksi ensimmäisenä piirrätän nappia painamalla lähtötiedoista suorakaiteen muotoisen palan, sen perään piirretään kaksi kaaren pätkää, jotka kuvaavat kulmaa(esimerkiksi 23 astetta). Uusien tietojen syöttämisen ja seuraavan napin painalluksen jälkeen olisi tarkoitus piirtää seuraava suorakaiteen muotoinen palanen niiden kaaren pätkien jatkoksi. Ja sitten taas seuraavat kaaren pätkät piirretyn suorakaiteen perään jne. Jolloin lopulta muodostuu yhtenäinen kappale, jossa on suorakaiteen muotoisia paloja eri kulmissa ja kaaren pätkiä kuvaamassa taitosta kappaleessa.

Nyt olen yrittänyt piirtää kyseistä kappaletta Line ja circle metodilla. Ja olen onnistunutkin piirtämään muutamia suorakulmioita ja kaaren pätkiä. Ongelmanani on kuitenki se, että kyseisellä tavalla joudun kirjoittamaan hirveästi koodia erillaisten kulma mahdollisuuksien takia. Ja mitä eteemmäs kappaleessa pääsee, sitä enemmän pitää laskea mikä on se todellinen kulma muuttumattomaan koordinaatistoon nähden.

Onko siis olemassa jokin tapa esimerkiksi kääntää koordinaatistoa picturepoxissa? Saako suorakaiteen muotoisen palikan piirrettyä jotenkin kaltevaan asentoon? Vai onko olemassa jokin apuneuvo kyseisen mallisen kappaleen piirtämiseen.

Jos jokin jäi epäselväksi kysy.

Terveisin Veikko

setä [25.07.2007 08:34:33]

#

Kuvaboxin ja formin koordinaatistoa ei voi kääntää vinoon, ainoastaan suunnan voi vaihtaa vastakkaiseksi ja origon paikkaa ja skaalausta muuttaa. Koordinaatiston kierto on siis hoidettava koodaamalla. Vinon suorakaiteen voi piirtää neljällä Line-käskyllä eli jokainen sivu erikseen koska Line-käskyssä B piirtää vain vaaka- ja pystyviivoja. Jos kuviot on täytettävä värillä on käytettävä API-kutsua ExtFloodFill, josta löytyy esimerkki Antin VB-oppaasta. Onko tarkoitus piirtää jonkinmoinen putki tai väylä vai mikä? Leveätä viivaa voi piirtää myös asettamalla DrawWidth riittävän suureksi.

Veikko [25.07.2007 08:56:53]

#

Juuri noin olen nyt tehnytkin: koodannut koordinaatisto muutokset, piirtänyt suorakaiteen neljällä line käskyllä. Olen kokeillut paksumpaa viivaa, mutta tullut siihen tulokseen että saan hienomman lopputuloksen, jos piirrän erillisistä viivoista.

Kyseessä on sellainen taivutettu metallilatta. Esimerkiksi kuparista 5 * 30 latta taivutetaan normaali tai sivuväärään suuntaan. Sitten siitä pitäisi piirtää kuva :)

Kiitos setä vastauksesta mutta ei auttanut hirveästi.

Terveisin Veikko

Grez [25.07.2007 09:03:46]

#

Lähinnä täytyy ihmetellä tuota, että "mitä eteemmäs kappaleessa pääsee, sitä enemmän pitää laskea"? Luulisi että melko helpolla laitat kappaleesi 3D koordinaatiston vektoreihin ja käännät katselukulman kertomalla sopivalla yksikkömatriisilla.

setä [25.07.2007 09:59:04]

#

Oletko piirtämässä 3D- vai 2D-kuvaa. Ymmärsin että 2D. Jos 2D riittää, voit kehitelä vinon suorakaiteen piirtorutiinin, jossa parametreina alkupiste, suunta ja pituus. Leveys taitaa olla vakio. Uudeksi alkupisteeksi tulee äskeisen piirron päätepiste. vastaavasti toinen rutiini kaarien piirtoon. Suunta ja pituus voidaan osoittaa hiirellä ja esim. vasemmalla napilla suorakaide ja oikealla kaari tai jokin muu valinta. Suorakaiteen kohdalla taitaakin suunta määräytyä edellisen kaaren mukaan. Kaaressa voi osoittaa kaaren päätepisteen, jolloin kaaren sädekin tulee määrätyksi.

Veikko [25.07.2007 10:01:33]

#

No niin Grez, nyt kuullostaa asialta!

Tajuan matemaattisesti mitä ajat takaa. Mutta mitä tuo tarkoittaa koodin kannalta?

Sedälläkin tuntuu olevan asiaa. 2D kuva on se mitä haen koska luulen että se on helpompi kuin 3D. 3D kuvan jos tekisin, kusisin samantien purkillisen hunajaa.

Piirtorutiinia suorakaiteille ja kulmille olen juuri parhaillani kehittämässä. Kehittelen sitä ja jos sen tiimoilta tulee kysyttävää kysyn, mutta nyt lähinnä halusin vastausta kysymykseen, että onko tapani käsitellä ongelmaa oikeanlainen(Circle, Line, koordinaatiston kääntö koodilla, jne.).

Piirrettävänä olevan kappaleen tiedot saadaan käyttäjän syöttäminä: esimerkiksi kaarenpätkän säde ja kulma sekä suorakaiteen pituus, leveys on vakio.

setä [25.07.2007 10:37:24]

#

Juuri Line- ja Circle-käskyillä, mutta en kiertäisi koordinaatistoa vaan suuntakulma tulisi parametrina piirtorutiineihin. Jos data syötetään numeroina, kannattaa muutkin piirtokomennot syöttää näppäimillä eikä käyttää hiirtä lainkaan. Esim. tyyliin:aluksi annetaan alkupiste, alkusuunta ja leveys. Seuraavaksi määrätään piirretäänkö suora vai kaari. Sen jälkeen suorasta annetaan pituus, kaaresta säde ja kulma tai keskiviivan pituus ja kulma. Jotenkin näin sitä itse kehittelisin.

Grez [25.07.2007 12:40:40]

#

Joo no siis eihän 3D ja 2D systeemissä ole muuta eroa kuin että 3D-systeemissä on 3 lukua ja 2D-systeemissä 2 lukua. Eli toki sen voi pistää 2D koordinaatteina 2 yksikön vektoreihin ja kertoa 2*2 kokoisella matriisilla. Ajattelin vaan että halusit saada siihen jonkinlaisen perspektiivin myös, jolloin on loogisempaa kääntää 3D-avaruudessa ja laskea perspektiivi z-koordinaatin perusteella.

Tosin ainakin 3D käännettyjen kaarien mallintaminen circle-käskyllä voi olla vaikeaa.

Veikko [25.07.2007 14:15:26]

#

Moro Grez

Kiitti taas valaistuksesta, mutta en oikein tajua koodin kannalta tota sinun matriisilla kertomista! Mitä se on? pistätkö esimerkin jos vain voit.

Joo circle käskyllä jos tekee 3D mallin niin kusen ämpärillisen hunajaa!

Jaska [25.07.2007 17:57:32]

#

Matriisin avulla kierrot saadaan esitettyä näppärästi. Jos tason vektoria v=[v_x v_y]^T halutaan kiertää origon ympäri a radiaania, uuden koordinaatit saadaan matriisitulosta
[v_x']=[cos a -sin a][v_x]
[v_y'] [sin a cos a][v_y].

Kaikki tason kierrot voidaan palauttaa tähän kiinnittämällä origoksi kiertopiste.

setä [25.07.2007 18:57:05]

#

Onkohan VB6:ssa matriisioperaatioita ?

setä [27.07.2007 01:12:03]

#

Joko keksit ratkaisun Veikko? Kiinnosti tehtävä sen verran että sohlasin oman ratkaisun, noin parisataa riviä. Hiirellä säätäen kaikki jolloin on helpompi testailla. Voin laittaa koodin tänne jos kiinnostaa.

Veikko [27.07.2007 08:09:18]

#

Moi

Tein sitä omaa versiotani mutta en saanut siitä puristettua sellaista yleistä mallia joka sopisi monimutkaisen kappaleen piirtämiseen. Yhden tavan keksin eilen ja sitä olisi koitettava tänään.

Jos setä laitat niin olen todella kiitollinen on kiva nähdä miten olet asiaa mietiskellyt.

terveisin Veikko

setä [27.07.2007 09:29:52]

#

Toiminta lyhyesti:
1. Valitaan aloituspiste painamalla hiiripainike alas (vasen tai oikea) sekä valitaan aloitussuunta ja leveys vetämällä hiirtä haluttuun suuntaan nappi painettuna. Reunaviiva piirtyy samalla osoittaen leveyden ja suunnan. Kun säätö on kohdallaan vapautetaan painike.
2. Valitaan vasemmalla painikkeella suorakaiteen pituus tai oikealla painikkeella sektoriraidan pituus ja kulma kuten edellä raahaamalla.
3. Toistetaan kohtaa 2 ja lopetus painamalla hiiren keskimmäistä nappia jonka jälkeen voi piirtää toisen kuvion. Ruudun tyhjennys painamalla C-kirjainta.

Option Explicit

Dim i As Integer, j As Integer
Dim px() As Single, py() As Single
Dim x0 As Single, y0 As Single
Dim r As Single, k As Single
Dim x1 As Single, y1 As Single
Dim x2 As Single, y2 As Single
Dim l As Single, lx As Single, ly As Single
Dim s As Single, ro As Single
Dim d As Single, pii As Single
Dim si As Single, co As Single
Dim dx As Single, dy As Single
Dim a1 As Single, a2 As Single 'kaaren alku- ja loppukulma
Dim a0 As Single, xe As Single, ye As Single
Dim c As Long 'piirtoväri

Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
  If KeyCode = vbKeyC Then
    i = 0: Cls
  End If
End Sub

Private Sub Form_Load()
  ReDim px(0), py(0)
  Caption = "Alkupiste"
  pii = 3.14159265
End Sub

Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
  DrawMode = 7 'kuminauhatila
  c = &HFFFF& 'piirtovärin komplementti
  If i = 0 Then
    px(i) = X: py(i) = Y 'aloituspiste
    Caption = "Suunta ja leveys"
    x1 = X: y1 = Y
    x2 = X: y2 = Y
    PSet (X, Y), c
  Else
    dx = X - px(i - 1)
    dy = Y - py(i - 1)
    If Button = 1 Then 'suorat
      Caption = "Suorakaiteen pituus"
      sarvot
      suorat
    ElseIf Button = 2 Then 'kaaret
      Caption = "Sektoriraidan pituus ja kaarevuus"
      kulma
      If k = s Then 'säde ääretön => suora

      Else
        r = l / Sin(s - k) 'kaaren säde
        If Abs(r) < d / 2 + 5 Then r = Sgn(r) * (d / 2 + 5)
        karvot
        Line (X - d * Cos(a0) / 2, Y - d * _
        Sin(a0) / 2)-Step(d * Cos(a0), d * Sin(a0)), c
        kaaret
        xe = X: ye = Y
      End If
    End If
  End If
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)

  If i = 0 Then
    If Button = 1 Or Button = 2 Then 'säädetään leveys ja aloitussuunta
      Line (x1, y1)-(x2, y2), c
      d = (Y - py(i)) / 2
      x1 = px(i) + d
      x2 = px(i) - d
      d = (X - px(i)) / 2
      y1 = py(i) - d
      y2 = py(i) + d
      Line (x1, y1)-(x2, y2), c
    End If
  Else
    dx = X - px(i - 1)
    dy = Y - py(i - 1)
    Select Case Button
    Case 1 'suorat
      suorat 'pyyhitään edelliset
      sarvot 'uudet arvot
      suorat
    Case 2 'kaaret
      kulma

      If k = s Then 'säde ääretön => suora

      Else
        Line (xe - d * Cos(a0) / 2, ye - d * _
        Sin(a0) / 2)-Step(d * Cos(a0), d * Sin(a0)), c
        kaaret
        ro = l / Sin(s - k) 'kaaren säde
        If Abs(ro) > d / 2 + 5 Then
          r = ro
          karvot
          Line (X - d * Cos(a0) / 2, Y - d * _
          Sin(a0) / 2)-Step(d * Cos(a0), d * Sin(a0)), c 'poikkiviiva
          kaaret
          xe = X: ye = Y
        End If
      End If
    End Select
  End If
End Sub

Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
  DrawMode = 13 'piirtotila
  c = 0 'piirtoväri musta
  If i = 0 Then
    Line (x1, y1)-(x2, y2), c 'alkureuna
    Caption = "Vasen painike: suora, oikea: kaari"
    dy = Y - py(i): dx = X - px(i)
    If dx > 0 Then
      s = Atn(dy / dx) 'suunta
    ElseIf dx < 0 Then
      s = pii + Atn(dy / dx)
    Else
      s = pii / 2 * Sgn(dy)
    End If
    d = Sqr(dx * dx + dy * dy) 'leveys
    If d = 0 Then  'virhe
      Cls
      Exit Sub
    End If
    si = dy / d: co = dx / d 'sin ja cos, tarvitaan myöhemmin
  Else
    If Button = 1 Then 'suorakaide
      suorat
      x1 = x1 + lx: y1 = y1 + ly 'uudet päätepisteet
      x2 = x2 + lx: y2 = y2 + ly
      px(i) = px(i - 1) + lx 'taulukkopiste
      py(i) = py(i - 1) + ly
    ElseIf Button = 2 Then 'sektoriraita
      kaaret
      dx = d * Cos(a0) / 2: dy = d * Sin(a0) / 2
      x1 = X - dx: x2 = X + dx
      y1 = Y - dy: y2 = Y + dy
      Line (x1, y1)-(x2, y2) 'poikkiviiva

      s = 2 * k - s 'suunta
      If s > 3 * pii / 2 Then s = s - 2 * pii
      If s < -pii / 2 Then s = s + 2 * pii

      si = Sin(s): co = Cos(s)
      px(i) = X: py(i) = Y
    Else
      i = 0: Exit Sub
    End If
  End If
  i = i + 1
  ReDim Preserve px(i), py(i)
End Sub

Private Sub Form_Resize()
  Me.ScaleMode = 3
  Me.ScaleHeight = -Abs(Me.ScaleHeight) 'origo vasemmalle alas
  Me.ScaleTop = Abs(Me.ScaleHeight)
End Sub

'suorien komponentit
Sub sarvot()
  l = dx * co + dy * si
  lx = l * co
  ly = l * si
End Sub

'suorakaiteen piirto
Sub suorat()
  Dim cx As Single, cy As Single
  Line (x1, y1)-Step(lx, ly), c 'suora
  cx = CurrentX: cy = CurrentY
  Line (x2, y2)-Step(lx, ly), c 'toinen suora
  Line -(cx, cy), c
End Sub

Sub kaaret()
  Circle (x0, y0), r + d / 2, c, a1, a2
  Circle (x0, y0), r - d / 2, c, a1, a2
End Sub

'kaaren kulman laskeminen
Sub kulma()
  l = Sqr(dx * dx + dy * dy) / 2
  If dx > 0 Then
    k = Atn(dy / dx)
  ElseIf dx < 0 Then
    k = pii + Atn(dy / dx)
  Else
    k = Sgn(dy) * pii / 2
  End If
End Sub

'kaarien arvot
Sub karvot()
  x0 = px(i - 1) + r * si
  y0 = py(i - 1) - r * co
  If r > 0 Then
    a1 = 2 * k - s + pii / 2
    a2 = s + pii / 2
    a0 = a1
  Else
    r = -r
    a2 = 2 * k - s + 3 * pii / 2
    a1 = s + 3 * pii / 2
    a0 = a2
  End If
  Do While a1 > 2 * pii
    a1 = a1 - 2 * pii
  Loop
  Do While a2 > 2 * pii
    a2 = a2 - 2 * pii
  Loop
  If a1 < 0 Then a1 = a1 + 2 * pii
  If a2 < 0 Then a2 = a2 + 2 * pii
End Sub

Veikko [27.07.2007 09:50:32]

#

Hieno on kuin helvetti :)

Ennen kuin tutustun enempää, haluan kokeilla omaa versiotani, jos siitä olisi johonkin. Kiitos vaan, ainakin tuli todistettua, että tuollaisen piirtäminen on täysin mahdollista.

Ilmoittelen edistymisestäni...

Terveisin Veikko

Veikko [30.07.2007 15:57:07]

#

Moi

Sain viimeisteltyä oman versioni tästä latan piirtämisestä. Ja hienosti tuntuu toimivan. Kiitos vain kaikille asiaan sotkeutuneille!

Kuitenkin yksi mutta! Nyt piirrettävä "mato" saattaa mennä jossain kohdassa ulos pictureboxista. Onko mahdollista että piirtää toiseen Pictureboxiin ja sitten sen saisi tulostettua/printattua keskelle toista kuvaa kokonaan näkyviin ja tietysti mahdollisimman isolla suurennoksella.

Nykyisin määrittelen skaalan Pictureboxille ensimmäisen suoran mukaan. Eli jos ensimmäinen suora on lyhyt saattaa loput pätkät mennä jo pois kuvasta.

Mikä neuvoksi?

Ajattelin ,että voisikohan CurrentX ja CurrentY tietoja käyttää hyväkseen, koska nehän kertovat missä suurimmat piirretyt arvot ovat.

Terveisin Veikko

setä [30.07.2007 16:29:14]

#

Tuota ongelmaa varten tallensin tietyt pisteet taulukkoon jotta kuvion voi piirtää uudelleen. Jos muutat skaalausta, kuvio ei muutu kuin piirtämällä se uudelleen tai zoomaamalla esim PaintPicture-metodilla mikä taas ei aina ole hyvä keino. Eli paras tapa on tallentaa syötetty data niin että kuvio on mahdollista uudelleenpiirtää. Näin siihen voi myös lisätä muokkausmahdollisuuden eli voi jotain kohtaa kuviossa muuttaa tarvitsematta syöttää kaikkea dataa uudelleen.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta