Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Как нарисовать график функции в СИ (compiler - bcc OR lcc)

Автор: zam
Дата сообщения: 11.02.2003 17:44
Дана функция, например f(x) = (1+(sin(x))^1/3)^1/3
Нужно пострить ее график, по точкам, масштабируя на весь экран, с оставленными полями по 1 см сверху/снизу/справа/слева, с координатной осью (просто крест, без стрелок) по центру, в зависимости от введенных координат - допустим (-3;3) мастабировать на весь экран, как и допустим с координатами (-10;10). Как?
Автор: Mickey_from_nsk
Дата сообщения: 12.02.2003 07:52
Номана сказано. Теперь детали. Как надо рисовать? в какой ОС, какими средствами?
Можно много всякого наворотить. От простенького окошка с графиком, если задача - просто посмотреть, что это такое, до целого графикового процессора с интерпретацией формул.
Короче, в чем задача то?
Автор: zam
Дата сообщения: 12.02.2003 17:25
Mickey_from_nsk
окон не надо, это лишнее. чистый дос, вывод на экран, во весь экран. код сишный
Автор: Mickey_from_nsk
Дата сообщения: 13.02.2003 09:43
Так чего ж тебе надо? Теорию? или уже все готовое?
Автор: zam
Дата сообщения: 13.02.2003 20:19
Mickey_from_nsk
график кстати такой: f(x) = tg(x) -- тангенс
--
Я не представляю как сделать масшабирование и как в принципе вывести на экран график (по точкам - в цикле - изменяя x на, допустим, 0.01). Но как это выглядит программно. Можно идеи, можно код, буду только рад!
Автор: rew
Дата сообщения: 13.02.2003 21:06
вот когда писал по этому поводу

Код:
#include <stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<graphics.h>
#include<math.h>
#include<dos.h>
//#define bgipath "a:\\bgi"
#define bgipath "d:\\borlandc\\bgi"
class axes
{
private:
int xcent,ycent,xend,yend;
float x,xt,y,yt,a,b,c;
void init();
public:
int x0,y0;//nachalo otnositel`no (0,0) ekrana
int xmin,ymin;//nachlo okna otnositelno (x0,y0)
int xmax,ymax;//konec""""""""""""""""
int bc,gc,fc;//border color,grid color,fill color
int gstp;//zoomgrid step
int grdstp; //grid step
float fstp; //func step
float zoom; //zoom
int ax;//show grid on/off

//axes4(int x0,int y0,int xmin,int ymin,int xmax,int ymax,int bc,int gc,int fc,int ax);//constructor
//axes(int,int,int,int,int,int,int,int,int,int,int,int);

axes()
{
x0=y0=20;
xmin=-120;xmax=120;
ymin=-100;ymax=100;
bc=12;
gc=10;
fc=7;
zoom=1;
grdstp=1;
fstp=zoom/10.0;
gstp=1/fstp*grdstp;
ax=1;
a=1;
b=16;
c=8;
} //end of constructor */
void draw_grid();
void draw_function();
void clear();
}; //end of class


void graphit (char *path)
{
int gd, gm , err ;
gd = 9 ;
gm = 2 ;

initgraph (&gd, &gm, path);


err = graphresult();
/* an error occurred */
if (err != grOk)
{
printf("Graphics error: %s\n", grapherrormsg(err));
printf("Press any key to halt:");
getch();
exit(1);
}
}
void axes::init()
{
xcent=x0-xmin;
ycent=y0+ymax;
xend=xcent+xmax;
yend=ycent-ymin;
fstp=zoom/1.0;
gstp=18/fstp*3.141592*grdstp;

}
void axes::clear()
{
init();
setfillstyle(1,0);
bar(x0,y0,xend,yend);
}
void axes::draw_grid()
{
init();
if(xend>639) //??????
xend=639; //??????
if(yend>479) //??????
yend=479; //??????
setcolor(bc);
rectangle(x0,y0,xend,yend);
setcolor(fc);
if(ycent>y0&&ycent<yend)
line(x0,ycent,xend,ycent);
else
{
setcolor(fc-2);
if(ycent<=y0)
line(x0,y0,xend,y0);
else
line(x0,yend,xend,yend);
}
setcolor(fc);
if(xcent>x0&&xcent<xend)
line(xcent,y0,xcent,yend);
else
{
setcolor(fc-2);
if(xcent<=x0)
line(x0,y0,x0,yend);
else
line(xend,y0,xend,yend);
}
if(gstp<2)
gstp=0;
if(gstp&&ax)
{
for(x=-xmin%gstp+x0;x<xend;x+=gstp)
for(y=ymax%gstp+y0;y<yend;y+=gstp)
if(x>x0&&y>y0)
putpixel(x,y,gc);
}
}

void axes::draw_function()
{
int sign;
init();
for(x=xmin,xt=xmin*fstp;x<=xmax;x++,xt+=fstp)
{
y=sin((3.141592/180)*xt)*180/3.141592;//a*pow(xt,2)+b*xt+c;
yt=sin((3.141592/180)*(xt+fstp))*180/3.141592;//a*pow((xt+fstp),2)+b*(xt+fstp)+c;
sign=y<yt?1:-1;
while(y*sign<yt*sign)
{
if(y/fstp>ymin&&y/fstp<ymax)
{
putpixel(x+xcent,ycent-y/fstp,4);
//delay(1);
}
y+=sign*fstp;
}
}
}

void main()
{
char ch=' ';
float zom[2]={10,10};
int i,up[2]={100,100},down[2]={-100,-100},left[2]={-100,-100},right[2]={100,100},step[2]={1,1},pres=0,grdstp[2]={1,1};
axes m[2];//(10,50,-100,-60,120,130,10,14,4,3,1);
graphit (bgipath) ;
m[1].x0=300;
m[1].y0=50;
m[0].x0=50;
m[0].y0=50;
for(i=0;i<2;i++)
{
m[i].xmin=left[i];
m[i].xmax=right[i];
m[i].ymin=down[i];
m[i].ymax=up[i];
m[i].zoom=zom[i];
m[i].draw_grid();
m[i].draw_function();
}

while(ch!='q')
{
ch=getch();
switch(ch)
{
case 'e':up[pres]-=step[pres];down[pres]-=step[pres];break;
case 'x':up[pres]+=step[pres];down[pres]+=step[pres];break;
case 'd':left[pres]-=step[pres];right[pres]-=step[pres];break;
case 's':left[pres]+=step[pres];right[pres]+=step[pres];break;
case '6':zom[pres]+=.1;break;
case '5':if(zom[pres]>0.1)zom[pres]-=.1;break;
case '7':if(step[pres]) step[pres]--;break;
case '8':step[pres]++;break;
case 'h':up[pres]=100;down[pres]=-100;left[pres]=-100;right[pres]=100;break;
case '1':pres=0;break;
case '2':pres=1;break;
case 'o':if(grdstp[pres]>1)grdstp[pres]--;break;
case 'p':grdstp[pres]++;
}
m[pres].grdstp=grdstp[pres];
m[pres].xmin=left[pres];
m[pres].xmax=right[pres];
m[pres].ymin=down[pres];
m[pres].ymax=up[pres];
m[pres].zoom=zom[pres];
m[pres].clear();
m[pres].draw_grid();
m[pres].draw_function();
}
getch();
}
Автор: zam
Дата сообщения: 13.02.2003 21:16
rew
у меня не пашет, хотя путь к bgi указал правильно. компилит, но ошибки при линковании.
Как избавиться от классов?
Автор: rew
Дата сообщения: 13.02.2003 21:28
у меня 3й борланд в нем нужно зайти в options->linker->libraries и отметить graphics library
как избавиться от класов? тебе вероятней всего нужны будут 2 функции, это draw_function() она рисует сам график и draw_grid() она рисует сетку и "окно" весь "основной код" находится в них. они тянут много переменных, но там вроде подписано что делает каждый из них и их можно сделать глобальными

Добавлено
вот вариант на си с тебя пиво

Код:
#include <stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<graphics.h>
#include<math.h>
#include<dos.h>
//#define bgipath "a:\\bgi"
#define bgipath "d:\\borlandc\\bgi"
int xcent,ycent,xend,yend;
float x,xt,y,yt;
int x0=20,y0=20;//nachalo otnositel`no (0,0) ekrana
int xmin=-120,ymin=-100;//nachlo okna otnositelno (x0,y0)
int xmax=120,ymax=100;//konec""""""""""""""""
int bc=12,gc=10,fc=7;//border color,grid color,fill color
int grdstp=1; //grid step
float zoom=1; //zoom
float fstp=zoom/10.0; //func step
int gstp=1/fstp*grdstp;//zoomgrid step
int ax=1;//show grid on/off



void graphit (char *path)
{
int gd, gm , err ;
gd = 9 ;
gm = 2 ;

initgraph (&gd, &gm, path);


err = graphresult();
/* an error occurred */
if (err != grOk)
{
printf("Graphics error: %s\n", grapherrormsg(err));
printf("Press any key to halt:");
getch();
exit(1);
}
}
void init()
{
xcent=x0-xmin;
ycent=y0+ymax;
xend=xcent+xmax;
yend=ycent-ymin;
fstp=zoom/1.0;
gstp=18/fstp*3.141592*grdstp;

}
void clear()
{
init();
setfillstyle(1,0);
bar(x0,y0,xend,yend);
}
void draw_grid()
{
init();
if(xend>639) //??????
xend=639; //??????
if(yend>479) //??????
yend=479; //??????
setcolor(bc);
rectangle(x0,y0,xend,yend);
setcolor(fc);
if(ycent>y0&&ycent<yend)
line(x0,ycent,xend,ycent);
else
{
setcolor(fc-2);
if(ycent<=y0)
line(x0,y0,xend,y0);
else
line(x0,yend,xend,yend);
}
setcolor(fc);
if(xcent>x0&&xcent<xend)
line(xcent,y0,xcent,yend);
else
{
setcolor(fc-2);
if(xcent<=x0)
line(x0,y0,x0,yend);
else
line(xend,y0,xend,yend);
}
if(gstp<2)
gstp=0;
if(gstp&&ax)
{
for(x=-xmin%gstp+x0;x<xend;x+=gstp)
for(y=ymax%gstp+y0;y<yend;y+=gstp)
if(x>x0&&y>y0)
putpixel(x,y,gc);
}
}

void draw_function()
{
int sign;
init();
for(x=xmin,xt=xmin*fstp;x<=xmax;x++,xt+=fstp)
{
y=sin((3.141592/180)*xt)*180/3.141592;//a*pow(xt,2)+b*xt+c;
yt=sin((3.141592/180)*(xt+fstp))*180/3.141592;//a*pow((xt+fstp),2)+b*(xt+fstp)+c;
sign=y<yt?1:-1;
while(y*sign<yt*sign)
{
if(y/fstp>ymin&&y/fstp<ymax)
{
putpixel(x+xcent,ycent-y/fstp,4);
//delay(1);
}
y+=sign*fstp;
}
}
}

void main()
{
char ch=' ';
int step=1;
// axes m[2];//(10,50,-100,-60,120,130,10,14,4,3,1);
graphit (bgipath) ;
x0=300;
y0=50;

xmin=-100;//left[-100];
xmax=100;//right[i];
ymin=-100;//down[i];
ymax=100;//up[i];
zoom=10;//zom[i];
draw_grid();
draw_function();


while((ch=getch())!='q')
{
switch(ch)
{
case 'e':ymax-=step;ymin-=step;break;
case 'x':ymax+=step;ymin+=step;break;
case 'd':xmin-=step;xmax-=step;break;
case 's':xmin+=step;xmax+=step;break;
case '6':zoom+=.1;break;
case '5':if(zoom>0.1)zoom-=.1;break;
case '7':if(step) step--;break;
case '8':step++;break;
case 'h':ymax=100;ymin=-100;xmin=-100;xmax=100;break;
case 'o':if(grdstp>1)grdstp--;break;
case 'p':grdstp++;
}

clear();
draw_grid();
draw_function();
}
getch();
}
Автор: Mickey_from_nsk
Дата сообщения: 14.02.2003 07:21
К данному тексту я бы еще добавил пару замечаний из собственного опыта.
1 Шаг сетки и начало ее отсчета может выбираться исходя из минимума длины координаты. То есть, вместо того, чтобы тупо брать, например, левый край сетки - -0.3334, затем с шагом 0.12321 рисовать засечки (или сетку), можно сделать первую засечку в точке -0.3, а шаг выбрать 0.1. Это делается достаточно просто.
xstep=10^((float)((int)log10(xmax-xmin)))/nsteps, где xmin и xmax - реальные края оси координат, nsteps - число отрисовок сетки. Далее, если ось координат входит в видимую область, рисуем от нее вправо и влево, иначе - по той же формуле находим самую левую засечку и рисуем относительно нее.
2. Шаг отрисовки функции лучше вычислять исходя из количества видимых пикселов на экране. Это чтобы лишнее не рисовать.
Автор: zam
Дата сообщения: 17.02.2003 00:32
rew
Большое СПАСИБО. В коде я пока не разбирался, пишу сейчас совсем другое (определение CRC, контрольных сумм).

Как сделать не точки на осях, а черточки - засечки с подписями цифр под ними?
Как нарисовать функцию ln(1+x)?
Автор: rew
Дата сообщения: 17.02.2003 04:08
полоски...

Код:
for(x=-xmin%gstp+x0;x<xend;x+=gstp){
line(x,ycent-5,x,ycent+5);
}
Автор: zam
Дата сообщения: 17.02.2003 20:27
Получается график функции sqrt(x). Т.е от нуля отсчет и как положено, хотя логарифмическая ф-ия равна нулю в точке 1. Что не так?
Автор: rew
Дата сообщения: 17.02.2003 22:27
угу нужно писать

Код: if(xt+1<=0){
continue;
}
Автор: zam
Дата сообщения: 18.02.2003 01:41
rew
Однако график получается правильным в случае:

Код:
void draw_function(void) {
int sign;

init();

for(x=xmin,xt=xmin*fstp; x<=xmax; x++,xt+=fstp) {
if(xt-1<=0)
continue;

y = log(xt-1);
yt = log(xt+fstp-1);
Автор: rew
Дата сообщения: 18.02.2003 01:48
zam
может быть я на точность для всех функций не претендую - для синуса и параболы, то что мне нужно было отобразить, вроде работало нормально


Добавлено

Код:
if(ycent>y0&&ycent<yend)
line(x0,ycent,xend,ycent); //если горизонтальная ось "находится" в окне
else
{
setcolor(fc-2);
if(ycent<=y0)
line(x0,y0,xend,y0); //если "выше" окна верхняя грань "окна" помечается другим цветом
else
line(x0,yend,xend,yend);// если "ниже" окна помечается нижняя грань
}
setcolor(fc);
if(xcent>x0&&xcent<xend)
line(xcent,y0,xcent,yend); //аналогично вертикальная ось
else
{
setcolor(fc-2);
if(xcent<=x0)
line(x0,y0,x0,yend);
else
line(xend,y0,xend,yend);
}
Автор: zam
Дата сообщения: 18.02.2003 23:11
rew

Код:
void draw_function(void) {

int sign;

init();

for(x=xmin+jmp,xt=xmin*fstp; x<=xmax-jmp; x++,xt+=fstp) {
y = sin((3.141592/180)*xt)*180/3.141592;
yt = sin((3.141592/180)*(xt+fstp))*180/3.141592;
sign = y < yt ? 1 : -1;

while(y*sign<yt*sign) {
if(y/fstp>ymin && y/fstp<ymax) {
putpixel(x+xcent,ycent-y/fstp,4);
//delay(1);
}

y += sign*fstp;
}
}
}
Автор: rew
Дата сообщения: 18.02.2003 23:35
zam
фактически там чертится ветикальная линия с (x+xcent,y,x+xcent,yt) но почему я не написал просто line(x+xcent,y,x+xcent,yt) а сделал "вручную", чтоб если линия вылазит за пределы "окна" ее не рисовало
Автор: zam
Дата сообщения: 18.02.2003 23:49
rew
У тебя при масштабировании ('5') получается отличный от рядового зума эффект. График движется относительно вертикальной и горизонтальной осей. Это все таки не зум. Знаешь, как изменить алгоритм?

Линии лучше рисовать от центра, иначе отрезки с учетом осей будут различны:в
как я сделал:

Код:
for(x=xcent;x<xend-jmp;x+=gstp+10) // vertical lines
line(x,ycent-3,x,ycent+3);
for(x=xcent; x>x0+jmp; x-=gstp+10)
line(x,ycent-3,x,ycent+3);
for(y=ycent;y<yend-jmp;y+=gstp+10) // horizontal lines
line(xcent-3,y,xcent+3,y);
for(y=ycent;y>y0+jmp;y-=gstp+10)
line(xcent-3,y,xcent+3,y);
Автор: rew
Дата сообщения: 19.02.2003 00:03
zam
непонял
Автор: zam
Дата сообщения: 19.02.2003 00:05
zam
Не знаю только (ты знаешь?) как с учетом этого к каждой черточке привязать номер? Причем делать так, чтобы выводить в строгом соответствии -- сколько черточек, столько и чисел.

Добавлено
rew
в смысле отчет вести от точки пересечения координат (xcent, ycent)
Автор: rew
Дата сообщения: 19.02.2003 00:11
ну вот к примеру по этим координатам line(x,ycent-3,x,ycent+3); ты рисуешь линию те если тебе нужно нарисовать выше число то ты его должен нарисовать по координатам (x-[ширина цифр/2], ycent +- некоторое смещение)
Автор: zam
Дата сообщения: 19.02.2003 00:13
rew
а зачем y И(?) yt. Я попробовал сделать одно -- получил "волосатый" график. Попробовал исключить другое -- получил полузакрашенный график. Не понимаю этого момента вообще. помоги понять плиз
Автор: rew
Дата сообщения: 19.02.2003 00:13

Цитата:
в смысле отчет вести от точки пересечения координат (xcent, ycent)

и что это даст?

Добавлено
zam
я ж говорю оно рисует вертикальную линию начиная с y до yt.
я не знаю как обьяснить там fstp это "шаг" по оси х функции который соответсвует 1пикселю по х на экране. там получается y=f(xt) а yt=f(xt+fstp) те в промежетке между xt и xt+fstp на экране отображается отрезок вертикальной линии.
кста, а зачем тебе что то исключать?
или я что то не правильно понял...
Автор: zam
Дата сообщения: 19.02.2003 01:06
rew
Почему-то теперь с логарифмами виснет при попытке увеличить/уменьшить зум через case. Как думаешь - почему?


Код:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <graphics.h>
#include <math.h>
#include <dos.h>
#define bgipath "d:\\lang\\bc\\bgi"
int xcent,ycent,xend,yend;

float x,xt,y,yt;
int x0=0, y0=0; //nachalo otnositel`no (0,0) ekrana
int xmin=0, ymin=0; //nachlo okna otnositelno (x0,y0)
int jmp=35;
int xmax=639, ymax=479; //konec
int bc=2, gc=10, fc=7; //border color,grid color,fill color
int grdstp=1; //grid step
float zoom=1; //zoom
float fstp; //func step
int gstp; //zoomgrid step
int ax=0; //show grid on/off

void graphit(char *path) {
int gd, gm, err;
gd = 9;
gm = 2;

initgraph (&gd, &gm, path);

err = graphresult();

/* an error occurred */
if (err != grOk) {
printf("Graphics error: %s\n", grapherrormsg(err));
printf("Press any key to halt:");
getch();
exit(1);
}
}

void init(void) {
xcent = x0 - xmin;
ycent = y0 + ymax;
xend = xcent + xmax;
yend = ycent-ymin;
fstp = zoom / 1.0;
gstp = 4;
}

void clear(void) {
init();
setfillstyle(1,0);
bar(x0,y0,xend,yend);
}

void draw_grid(void) {
init();
if(xend>639)
xend=639;

if(yend>479)
yend=479;

setcolor(bc);
rectangle(x0+jmp,y0+jmp,xend-jmp,yend-jmp);
setcolor(fc);

if(ycent>y0 && ycent<yend)
line(x0+jmp,ycent,xend-jmp,ycent);

setcolor(fc);

if(xcent>x0 && xcent<xend)
line(xcent, y0+jmp, xcent, yend-jmp);

if(gstp<2)
gstp=0;

if(gstp && ax) {
for(x=-xmin%gstp+x0; x<xend; x+=gstp)
for(y=ymax%gstp+y0; y<yend; y+=gstp)

if(x>x0 && y>y0)
putpixel(x, y, gc);
}
}

void draw_function(void) {
int sign;
init();

for(x=xmin+jmp,xt=xmin*fstp; x<=xmax-jmp; x++,xt+=fstp) {
if(xt-1<=0)
continue;
y = log(xt-1);
yt = log(xt+fstp-1);
sign = y < yt ? 1 : -1;

while(y*sign<yt*sign) {
if(y/fstp>ymin && y/fstp<ymax) {
putpixel(x+xcent,ycent-y/fstp,4);
}
y += sign*fstp;
}
}

for(x=xcent;x<xend-jmp;x+=gstp+10) // vertical lines
line(x,ycent-3,x,ycent+3);
for(x=xcent; x>x0+jmp; x-=gstp+10)
line(x,ycent-3,x,ycent+3);
for(y=ycent;y<yend-jmp;y+=gstp+10) // horizontal lines
line(xcent-3,y,xcent+3,y);
for(y=ycent;y>y0+jmp;y-=gstp+10)
line(xcent-3,y,xcent+3,y);
}

int main(void) {
char ch=' ';
graphit(bgipath);
x0=0;
y0=0;
xmin=-getmaxx()/2;
xmax=getmaxx()/2;
ymin=-getmaxy()/2;
ymax=getmaxy()/2;

zoom=12.52;
draw_grid();
draw_function();

while((ch=getch())!='q') {
switch(ch) {
case 'x':zoom+=.1;break;
case 'z':if(zoom>0.1)zoom-=.1;break;
}
clear();
}
getch();
return 1;
}
Автор: fuyoko
Дата сообщения: 20.04.2011 02:36
Эм привет всем)
а строфоиду как рисовать????0_0
сразу говорю я чайник в этом деле
Автор: XPEHOMETP
Дата сообщения: 21.04.2011 07:10
fuyoko

Цитата:
а строфоиду как рисовать????

Я буду неоригинален до крайности... Посмотрите начало этой темы, какие там вопросы задавали? Какая операционка (может, голый ДОС), куда выводим рисунок - в окошко или в консоль... И лично от себя: а нельзя ли использовать сторонние библиотеки или даже программы? Cкажем, gnuplot? Ну, похоже, задание учебное, стало быть, нельзя. Или же это только пойдет в плюс, как показатель навыков работы со сторонним софтом? Однако же, из сказанного выше, ничего не пригодилось? Не надо бить себя ногой в грудь и говорить: я - чайник. Все ими когда-то были, а в определенных областях остаются до сих пор. Объясните хотя бы, с чем у Вас реальные проблемы.

Страницы: 1

Предыдущая тема: Вопросы по компонентам для Delphi, C++ Builder


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.