Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C: Vinon viivan koordinaatit

Sivun loppuun

pielinen [28.12.2007 12:12:24]

#

En millään keksi koodia millä saisi vinon viivan kaikki pisteet väliltä.

Esim. x=200 y=300 ja x=100 y=50 Noitten välille siis piirretään jana, ja pitäisi saada kaikki janan varrelle jäävät kokonaisluvuista koostuvat koordinaatit.

Myös pitäisi pystyä syöttämään seuraava koordinaatit mihin piirrettäisiin edellisestä jana ja laskettaisiin koordinaatit

hunajavohveli [28.12.2007 12:31:16]

#

Laskemalla koordinaattien erotukset saadaan 100 - 200 = -100 ja 300 - 50 = 250. Näiden suhde (-100/250) sievenee muotoon -2/5, eli kaikki kokonaislukuparit saadaan käytyä läpi, kun aloitetaan pisteestä (200, 300) ja kasvatetaan x-koordinaattia luvulla -2 ja y-koordinaattia luvulla 5. Varsinainen ongelma lienee siis löytää tuo sievin mahdollinen muoto ja joissain tapauksissahan suhde ei edes sievene. Tässä näkyisi olevan esimerkki, jolla lukujen suurimman yhteisen tekijän voi löytää.

Edit: Putkaankin on näemmä kirjoitettu aiheesta.

Antti Laaksonen [28.12.2007 13:03:55]

#

Vai tarkoitatko tällaista piirtoa?

http://fi.wikipedia.org/wiki/Bresenhamin_algoritmi

Viivasta voi nimittäin tulla aika katkeileva, jos siihen hyväksytään ainoastaan pisteet, joiden koordinaatit osuvat tarkalleen kokonaislukuihin.

pielinen [28.12.2007 13:10:46]

#

Jep, Haussa oli justiinsa tuommoinen mihin Antti antoi linkin.

Tuo siis tulee osaksi cnc-kuumalanka leikkurin ohjaus ohjelmaa.

Dude [28.12.2007 15:20:30]

#

mä en saanu tuota bresenhamin algoritmiä toimimaan kunnolla

pielinen [28.12.2007 15:28:42]

#

Sain tämmöisen koodin aikaan.

#include <stdio.h>

int main(void) {

//Määrittelee muuttujia
float x0=0;
float y0=0;
float x1=0;
float y1=0;

float z;
float x;
float y;
float v;

int py;
int px;

//aloittaa ohjelman silmukan
while(1){
//lukee Koordinaatiti
scanf("%f %f",&x1,&y1);
//Laskee suhteen
z=(y1-y0)/(x1-x0);
//Laskee korjauksen
v=z*x0;
//tarkistaa onko x suurempi kuin janan alku
if(x0<x1){
//alottaa silmukan
for(x=x0; x<=x1 ; x++)
{
//laskee y arvon
y=z*x-v+y0;

//muuntaa kokonais luvuiksi
py=y;
px=x;
//tulostaa koordinaatiti
printf("X=%i ss Y=%i\n",px,py);
}
}
//tarkistaa onko janan loppu pienempi kuin alku
if(x0>x1){
//Aloittaa silmukan
for(x=x0; x>=x1 ; x--)
{
//laskee y arvon
y=z*x-v+y0;

//muuntaa arvot kokonais luvuiksi
py=y;
px=x;
//tulostaa koordinaatiti
printf("X=%i ss Y=%i\n",px,py);
}
}



//Antaa uudet alkupisteet.
x0=x1;
y0=y1;




}

}

Koodi on ehkä hitusen sekava, kun aloitin c koodaamisen toissa viikolla.

Metabolix [28.12.2007 17:14:38]

#

Intuitiivinen ratkaisu:

void jana(int x0, int y0, int x1, int y1)
{
  // Paljonko koordinaatit muuttuvat janan aikana?
  int dx = x1 - x0, dy = y1 - y0;
  // Janan pituus suurempaan suuntaan
  int l = max(abs(dx), abs(dy));

  int i;
  float t;
  for (i = 0; i <= l; ++i) {
    // 0 <= i/l <= 1, joten pisteet ovat janalla
    t = (float)i / l;
    pikseli(x0 + t * dx, y0 + t * dy);
  }
}

/* Tarvittaessa abs- ja max-funktiot: */
int abs(int x) {if (x < 0) return -x; else return x;}
int max(int x, int y) {if (x < y) return y; else return x;}

pielinen [28.12.2007 20:15:13]

#

Antaisitko koko koodin?
En oikeen tajunnut tuota.

aegis [28.12.2007 21:50:21]

#

Siinä on koko koodi.

Metabolix [28.12.2007 21:55:03]

#

Tuossahan se, kirjoitin sen suoraan tuohon noin. Funktio pikseli(x, y) piirtää pikselin tai muun pisteen kohtaan (x, y).

Eihän näillä kovin kaunista jälkeä tule ASCII-piirroksina ainakaan, mutta tuon oli tarkoitus vain näyttää, että kyllä jonkinlaisen viivan saa aikaan vähemmälläkin ajattelulla.

Parantelin funktiota vielä ja kirjoitin yksinkertaisen ohjelman sen ympärille:

#include <stdio.h>
#include <ctype.h>
#include <math.h>

/**
* Puskurin mitat ja puskuri merkkejä varten
**/
#define W (80 - 1)
#define H (25 - 1)

char buf[H][W+1] = {0};

void jana(int x0, int y0, int x1, int y1, char m);
void pikseli(int x, int y, char m);

int isomman_itseisarvo(int x, int y)
{
	if (x < 0) x = -x;
	if (y < 0) y = -y;
	if (x < y) return y;
	return x;
}

/**
* funktio jana - piirretään puskuriin jana (x0, y0) - (x1, y1) merkillä m
**/
void jana(int x0, int y0, int x1, int y1, char m)
{
	/* Paljonko koordinaatit muuttuvat janan aikana? */
	int dx = x1 - x0, dy = y1 - y0;

	/* Suuremman mitan itseisarvo pituudeksi */
	int l = isomman_itseisarvo(dx, dy);
	if (!l) {
		/* Pituus 0, piirretään piste */
		pikseli(x0, y0, m);
		return;
	}

	int i;
	float t;
	for (i = 0; i <= l; ++i) {
		/* 0 <= i/l <= 1, joten pisteet ovat janalla */
		t = (float)i / l;
		pikseli(x0 + t * dx + 0.5, y0 + t * dy + 0.5, m);
	}
}

/**
* funktio pikseli - piirretään puskuriin merkki m kohtaan (x, y)
**/
void pikseli(int x, int y, char m)
{
	if ((unsigned)x < W && (unsigned)y < H) {
		buf[y][x] = m;
	}
}

/**
* funktio flush - piirretään puskuri ruudulle
**/
void flush(void)
{
	int i, j;
	putchar('\n');
	for (i = 0; i < H; ++i) {
		for (j = 0; j < W; ++j) {
			if (isgraph(buf[i][j])) {
				putchar(buf[i][j]);
			} else {
				putchar(' ');
			}
		}
		putchar('\n');
	}
}

/**
* funktio main - pyydetään käyttäjältä pisteitä janaa varten ja piirretään
**/
int main(void)
{
	int x0 = 1, x1 = W, y0 = 1, y1 = H;
	char m = '0';
	do {
		/* Seuraava kelvollinen merkki */
		do { ++m; } while (!isgraph(m));

		/* Viiva tähän */
		jana(x0, y0, x1, y1, m);

		/* Piirto ruudulle */
		flush();

		/* Pyyntö */
		printf("Anna janan päät: x0 y0 x1 y1: ");
	} while (scanf("%d %d %d %d", &x0, &y0, &x1, &y1) == 4 && (x0 || x1 || y0 || y1));

	printf("Virheellinen syöte tai pelkkiä nollia, lopetetaan.\n");

	return 0;
}

Edit. Taitaakin olla muuten käytännössä Bresenhamin algoritmi tämäkin, vaikka desimaaliluvut piilottavat sen hankalimman osan.


Sivun alkuun

Vastaus

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

Tietoa sivustosta