Jak narysować "normalny" wielokąt w Allegro 5

0

Witam miałem ostatnio taki problem. Chciałem narysować za pomocą biblioteki Allegro 5 wielokąt. W tej bibliotece owszem funkcja do tego była lecz nie rysowała "normalnego" wielokąta.
Tzn. czasem rysowała a czasem nie zależnie od tego jakie tam były punkty podane. Więc napisałem funkcje sam do tego i chcę się nią podzielić może się komuś do czegoś przyda.
A jak by ktoś wytłumaczył mi jak za pomocą samej Allegro to zrobić to też będę wdzięczny. Gdzieś przeczytałem że A5 rysuje tylko selfoverlaped poligons tylko nie wiem co to znaczy.
Wiem że może nie napisałem tego zbyt wydajnie no ale lepsze coś niż nic i może komuś się przyda.

#include <stdio.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_image.h>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;

bool bolik=true;
typedef double posu;
class punkt{
public:
    posu x,y;
    punkt(posu xp=0,posu yp=0,ALLEGRO_COLOR cp=al_map_rgb(255,255,255))
    {
        x=xp;
        y=yp;
    }
    void pisz()
    {
    	cout<<" ("<<x<<","<<y<<")"<<endl;
    }
    ALLEGRO_COLOR c;	
   
};
bool operator<(punkt p1,punkt p2)
{
	return p1.x<p2.x;
}
		
punkt operator+(punkt p1,punkt p2)
{
	return punkt(p1.x+p2.x,p1.y+p2.y);
}		 	
punkt operator-(punkt p1,punkt p2)
{
	return punkt(p1.x-p2.x,p1.y-p2.y);
}	
punkt rotatepoint(punkt ptr,punkt pw,double k)// funkcja obracająca punkt ptr wzglendem punku pw i zwracajaca juz obrucony
{  
    if(!k)return ptr;                                    
    punkt wynik;
    double x1=ptr.x;
    double y1=ptr.y;
    double xo=pw.x;
    double yo=pw.y;
    wynik.x=(x1-xo)*cos(k) - (y1-yo)*sin(k)+xo;
    wynik.y=(x1-xo)*sin(k) + (y1-yo)*cos(k)+yo;
    return wynik;
}

void mm_draw_filled_polygon2(vector<punkt> v,ALLEGRO_COLOR c);


const int szer=800,wys=600;


    ALLEGRO_DISPLAY * display = NULL;
    ALLEGRO_EVENT_QUEUE * kolejka=NULL;
    ALLEGRO_EVENT zdazenie;
	ALLEGRO_TIMER * czas=NULL;	
	ALLEGRO_MOUSE_STATE state;
	

punkt m(szer/2,wys/2);
vector<punkt> wielok;
bool wci=false;
bool rysuj=false;
struct poligony{
	vector<vector<punkt> > p;
	vector<ALLEGRO_COLOR> c;
	void rysuj()
	{
		for(int i=0;i<p.size();i++)
		{
				mm_draw_filled_polygon2(p[i],c[i]);
		}
	}
	void obracaj(double a)
	{
		for(int i=0;i<p.size();i++)
			for(int j=0;j<p[i].size();j++)
				p[i][j]=rotatepoint(p[i][j],punkt(szer/2,wys/2),a);
	}
};
poligony gony;							
int main( int argc, char * argv[] )
{


	unsigned char r=0;
    /* Inicjalizacja biblioteki */
    if( !al_init() )
    {
        fprintf( stderr, "Failed to initialize allegro!\n" );
        return - 1;
    }
	al_install_keyboard();
	al_install_mouse();
	al_init_font_addon();
	al_init_primitives_addon();
	al_init_image_addon();
	
	ALLEGRO_KEYBOARD_STATE klawiatura;
	
	
	ALLEGRO_FONT* font8 = al_create_builtin_font();
	
	int x=140,y=100;
	int xm,ym;
	double t=al_get_time();
	kolejka=al_create_event_queue();   

    display = al_create_display( szer, wys );
    if( !display )
    {
        fprintf( stderr, "Failed to create display!\n" );
        return - 1;
    }
	al_register_event_source(kolejka,al_get_display_event_source(display));   

	czas=al_create_timer(1.0/30);
	al_register_event_source(kolejka,al_get_timer_event_source(czas));
	al_register_event_source(kolejka,al_get_keyboard_event_source());

	al_start_timer(czas);
	while(0){
		al_wait_for_event(kolejka,&zdazenie);
		if(zdazenie.type==ALLEGRO_EVENT_DISPLAY_CLOSE)
			break;
		if(zdazenie.type==ALLEGRO_EVENT_TIMER)
		{
			al_clear_to_color( al_map_rgb( ++r, 100, 150 ) );
			al_flip_display();
		}
	}
	double time=al_get_time();
	string nap="dupa";

	
	
	while(!al_key_down(&klawiatura,ALLEGRO_KEY_ESCAPE))//,al_draw_bitmap(bitmapa,x,y,0   
    {
			al_get_keyboard_state(&klawiatura);
			al_get_mouse_state(&state);
			xm=state.x;
			ym=state.y;
			
		if(al_get_time()>time+0.01)
		{	
			if(al_key_down(&klawiatura,ALLEGRO_KEY_R))rysuj=true;
			if(al_key_down(&klawiatura,ALLEGRO_KEY_X)){
				wielok.clear();
				rysuj=false;
			}
			if(al_key_down(&klawiatura,ALLEGRO_KEY_B))
			{
				bolik=!bolik;
				if(bolik)
					nap="wlonczone";
				else
					nap="wylonczone";
			}			
					
			time=al_get_time();
		}
		al_wait_for_event(kolejka,&zdazenie);
		if(zdazenie.type==ALLEGRO_EVENT_KEY_CHAR)
		{
			int kl=0;
			kl=zdazenie.keyboard.unichar;
			//cout<<kl<<endl;
			char asc = kl;// & 0xff;
			//char scancode = kl >>8;
			//if(asc>32 && asc<126)
				nap+=asc;
			//if(scancode==KEY_BACKSPACE)
			//{
			//	if( nap.length()>0)
            //             nap=nap.substr(0,nap.length()-1);
            //}
        }
        if(zdazenie.type==ALLEGRO_EVENT_DISPLAY_CLOSE)
			break;                		
		al_clear_to_color( al_map_rgb( ++r, 100, 150 ) );
		
		al_draw_text(font8,al_map_rgb(0,255,0),100,100,0,nap.c_str());
		int count=5;
		
		if(rysuj)
			mm_draw_filled_polygon2(wielok,al_map_rgba(0,0,0,123));
		//gony.rysuj();
		if(al_get_time()>12)
			gony.obracaj(0.01);	
		
		
		
	
		if((state.buttons & 1)&&!wci)
		{
			wci=true;
			wielok.push_back(punkt(xm,ym));
		}	
		for(int i=0;i<wielok.size();i++)
				al_draw_filled_ellipse(wielok[i].x,wielok[i].y,5,5,al_map_rgb(255,0,0));
		if(state.buttons & 1)
			wci=true;
		else
			wci=false;	
						
		al_flip_display();
	}			
   // al_rest( 10.0 );
    al_destroy_display( display );
	al_destroy_event_queue(kolejka);   
    return 0;
}


void wyjmij(punkt t,vector<punkt>&v)
{
	for(int i=0;i<v.size();i++)
	{
		if(t.x==v[i].x&&t.y==v[i].y)
			v.erase(v.begin()+i);
	}
}			
struct lil{
	double a,b;
	punkt p1,p2;
	bool ruw;
	posu minx,miny,maxx,maxy;
	void oblicz()
	{
		if(p1.x==p2.x)
		{
			ruw=true;
			return;
		}
		ruw=false;	
		a=(p1.y-p2.y)/(p1.x-p2.x);
		b=p1.y-a*p1.x;
	}
	bool jest(posu y)
	{
		if(y>miny&&y<maxy)
			return true;
		return false;
	}
	punkt traw(posu y)
	{
		if(!ruw && jest(y))
			return punkt((y-b)/a,y);// y=ax+b / y-b=ax x=(y-b)/a
		else
			return punkt(0,0);
	}					
	punkt wart(posu x){
		if(x<minx||x>maxx)
			return punkt(0,0);
		else if(ruw)
			return punkt(0,0);	
		else
			return punkt(x,a*x+b);
	}		
	lil(punkt p1p,punkt p2p)
	{
		p1=p1p;
		p2=p2p;
		minx=min(p1.x,p2.x);
		maxx=max(p1.x,p2.x);
		miny=min(p1.y,p2.y);
		maxy=max(p1.y,p2.y);
		oblicz();
	}		
		
};
bool isiny(posu y,vector<punkt>&v,vector<punkt>&v2)
{
	int prew,next;
	bool dxp,dyp,dxn,dyn;
	bool w=false;
	for(int i=0;i<v.size();i++)
	{
		
		if(i==v.size()-1)
		{
			prew=i-1;
			next=0;
		}else if(i==0)
		{
			prew=v.size()-1;
			next=i+1;
		}else{
			prew=i-1;
			next=i+1;
		}
				
		if(v[i].y==y)
		{
	//		dxp=v[prew].x<v[i].x;
///			dxn=v[next].x<v[i].x;
			dyp=v[prew].y<v[i].y;
			dyn=v[next].y<v[i].y;
			if(dyp==dyn||!dyp==!dyn)
				wyjmij(v[i],v2);
			else{
				v2.push_back(v[i]);
				w=true;
			}	
		}
	}
	return w;
}							
void mm_draw_filled_polygon2(vector<punkt> v,ALLEGRO_COLOR c)						
{
	//cout<<"wykonuje funkcje: mm_draw_filled_polygon2"<<endl;
	vector<lil> linie;
	for(int i=0;i<v.size();i++)
	{
		if(i==v.size()-1)
			linie.push_back(lil(v[i],v[0]));
		else
			linie.push_back(lil(v[i],v[i+1]));
	}
	vector<punkt> zakazane;
	vector<punkt> punkty;
	punkt temp;
	bool byl=false;
	int fr,to;
	for(int y=0;y<wys;y++)
	{
		//cout<<"poczatek lini:"<<endl;
		for(int i=0;i<linie.size();i++)
		{
			if(linie[i].jest(y)){
			
		//	temp.pisz();
			
				temp=linie[i].traw(y);
				for(int i=0;i<punkty.size();i++)
					if((int)punkty[i].x==(int)temp.x)
						continue;
					punkty.push_back(temp);
					
				
				}
			else
				continue;
		}
		//cout<<"koniec lini:"<<endl;
		if(bolik)isiny(y,v,punkty);
		sort(punkty.begin(),punkty.end());
		bool draw=true;

		for(int i=0;i<punkty.size();i++)
		{
			fr=punkty[i].x;
			to=punkty[i+1].x;
			if(draw)
				al_draw_line(fr,y,to,y,c,1);//pasek(y,fr,to,c);
			
			draw=!draw;	
		}
		punkty.clear();
	}	
}
0
dreammaker napisał(a):

Tzn. czasem rysowała a czasem nie zależnie od tego jakie tam były punkty podane

Czy to jest techniczny opis problemu?
Jakoś wątpię, by biblioteka tak stara jak allegro źle rysowała wielokąt (z drugiej strony jak patrze jak wygląda API to nie mam zaufania do allegro).
Albo źle używasz API, albo twoje oczekiwania są dziwne.

0

selfoverlaped poligons

Wielokąty wypukłe.

Nie używałem A5 ale podzielił bym wielokąt wklęsły na kilka wypukłych i wtedy je rysował.

1

Jeśli ktoś tworzy coś takiego jak kod powyżej. Może znaczć to, że nie zapoznał się z dokumentacją allegro.
void rect_draw(int x,int y, int w,int h,ALLEGRO_COLOR top_left,ALLEGRO_COLOR bottom_left,ALLEGRO_COLOR top_right,ALLEGRO_COLOR bottom_right)
{
ALLEGRO_VERTEX it_rect[] =
{
{ .x = x, .y = y, .z = 0, .color = top_left},
{ .x = x+w, .y = y, .z = 0, .color = top_right},
{ .x = x, .y = y+h, .z = 0, .color = bottom_left},
{ .x = x+w, .y = y+h, .z = 0, .color = bottom_right}
};
al_draw_prim(it_rect, NULL, NULL, 0, 4, ALLEGRO_PRIM_TRIANGLE_STRIP);
///wystarczy podać punkty jako ALLEGRO_VERTEX oraz ich ilość w 5 parametrze. Można w ten sposób stworzyć dowolny wielokąt.
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1