/****************************************************************** * * * Nest version 2 - 3D Wasp Nest Simulator * * Copyright (C) 1997 Sylvain GUERIN * * LIASC, ENST Bretagne & Santa Fe Institute * * * ****************************************************************** E-mail: Sylvain.Guerin@enst-bretagne.fr or: Sylvain Guerin 13 rue des Monts Lorgeaux, 51460 L'EPINE, FRANCE ****************************************************************** This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ****************************************************************** Name : view3d.c Component : 3D visualisation (View object) Fonctionality : contains methods for the View object (used in view and edition interfaces) ******************************************************************/ #include "view3d.h" #include "ViewInt.h" #include "algo.h" #include "tools.h" // ---------------------------------------------------------------- View::View (Display* aDisplay, Window aWin, GC aGC, Window aIconWin, unsigned long* manyColor, displayModeType aDisplayMode, unsigned int aWidth, unsigned int aHeight, XFontStruct *aFontInfo, unsigned int defaultDepth, Architecture* anArch, SimulationType aSimuType, Window aPreviewWindow) { previewWindow = aPreviewWindow; display = aDisplay; win = aWin; gc = aGC; iconWin = aIconWin; color = manyColor; width = (int)aWidth; height = (int)aHeight; fontInfo = aFontInfo; depth = defaultDepth; anArchitecture = anArch; displayMode = aDisplayMode; loadViewIconDatas (); tempScreen = XCreatePixmap (display, win, width, height, depth); showAxes = 1; hexaRoundSize = 1/(2*cos(pi/6)); zLenght = (tan (pi/6)+1/cos (pi/6))/2; simuType = aSimuType; zCut = 0; tetaCut = 0; phiCut = 0; }; void View::changeWindows (Window aWin, Window aIconWin) { win = aWin; iconWin = aIconWin; } // ---------------------------------------------------------------- void View::init_view (position init_viewed_point, position init_org, double initZoom, double initIconZoom, int iconTx, int iconTy) { int i; viewed_point = init_viewed_point; org = init_org; alpha = 0; alpha_matrix = Matrix2 (cos(alpha), sin(alpha), -sin(alpha), cos(alpha)); zoom = initZoom; zoom0 = zoom; teta = 0; phi = M_PI/2; for (i=0; i<30; i++) { mx[i] = 0; my[i] = 0; } settings_1 (); viewIconZoom = initIconZoom; viewIconTx = iconTx; viewIconTy = iconTy; }; void View::loadViewIconDatas () { position p; viewIconPosition = new position[12]; viewIconLine = new viewIconLineType[15]; p.x=2; p.y=5; p.z=2; loadViewIconPosition (p, 0); p.x=2; p.y=5; p.z=-2; loadViewIconPosition (p, 1); p.x=-2; p.y=5; p.z=-2; loadViewIconPosition (p, 2); p.x=-2; p.y=5; p.z=2; loadViewIconPosition (p, 3); p.x=4; p.y=-5; p.z=4; loadViewIconPosition (p, 4); p.x=4; p.y=-5; p.z=-4; loadViewIconPosition (p, 5); p.x=-4; p.y=-5; p.z=-4; loadViewIconPosition (p, 6); p.x=-4; p.y=-5; p.z=4; loadViewIconPosition (p, 7); p.x=0; p.y=0; p.z=0; loadViewIconPosition (p, 8); /* */p.x=6; p.y=0; p.z=0; loadViewIconPosition (p, 9); p.x=0; p.y=-6; p.z=0; /* 6 -6 */ loadViewIconPosition (p, 10); p.x=0; p.y=0; p.z=6; loadViewIconPosition (p, 11); loadViewIconLine (0, 1, 0); loadViewIconLine (1, 2, 1); loadViewIconLine (2, 3, 2); loadViewIconLine (3, 0, 3); loadViewIconLine (4, 5, 4); loadViewIconLine (5, 6, 5); loadViewIconLine (6, 7, 6); loadViewIconLine (7, 4, 7); loadViewIconLine (0, 4, 8); loadViewIconLine (1, 5, 9); loadViewIconLine (2, 6, 10); loadViewIconLine (3, 7, 11); loadViewIconLine (8, 9, 12); loadViewIconLine (8, 10, 13); loadViewIconLine (8, 11, 14); } void View::loadViewIconPosition (position pos, unsigned int index) { viewIconPosition[index] = pos; } void View::loadViewIconLine (unsigned int ext1, unsigned int ext2, unsigned int index) { viewIconLine[index].p1 = ext1; viewIconLine[index].p2 = ext2; } // ---------------------------------------------------------------- void View::settings_1 (void) { viewed_direction = get_direction_from_2_positions (org, viewed_point); eye_plan = get_plan_from_direction_and_position (get_direction_from_2_positions (org, viewed_point), org); work_plan = get_plan_from_direction_and_position (get_direction_from_2_positions (org, viewed_point), viewed_point); get_teta_phi_from_direction (viewed_direction, &teta, &phi); teta0 = teta; phi0 = phi; alpha0 = alpha; rotation_matrix.set_rotation (teta, phi); inverse_rotation_matrix = inverse (rotation_matrix); set_tx_ty_with_vp (); } // ---------------------------------------------------------------- void View::settings_2 (void) { int tx1, ty1; viewed_direction = get_direction_from_2_positions (org, viewed_point); eye_plan = get_plan_from_direction_and_position (get_direction_from_2_positions (org, viewed_point), org); work_plan = get_plan_from_direction_and_position (get_direction_from_2_positions (org, viewed_point),viewed_point); get_teta_phi_from_direction (viewed_direction, &teta, &phi); rotation_matrix.set_rotation (teta, phi); inverse_rotation_matrix = inverse (rotation_matrix); tx1 = tx; ty1 = ty; set_tx_ty_with_vp (); tx = tx1; ty = ty1; } // ---------------------------------------------------------------- void View::settings_3 (position sv_org, double sv_teta, double sv_phi, double sv_alpha, double sv_zoom) { double dist; dist = get_dist_positions (org, viewed_point); org = sv_org; teta = sv_teta+M_PI; phi = sv_phi; alpha = sv_alpha; zoom = sv_zoom; zoom0 = sv_zoom; viewed_point.x = -cos(phi)*cos(teta)*dist+org.x; viewed_point.y = -sin(phi)*dist+org.y; viewed_point.z = -cos(phi)*sin(teta)*dist+org.z; viewed_direction = get_direction_from_2_positions (org, viewed_point); eye_plan = get_plan_from_direction_and_position (get_direction_from_2_positions (org, viewed_point), org); work_plan = get_plan_from_direction_and_position (get_direction_from_2_positions (org, viewed_point),viewed_point); get_teta_phi_from_direction (viewed_direction, &teta, &phi); teta0 = teta; phi0 = phi; alpha0 = alpha; rotation_matrix.set_rotation (teta, phi); inverse_rotation_matrix = inverse (rotation_matrix); set_tx_ty_with_vp (); } // ---------------------------------------------------------------- View::~View () { XFreePixmap (display, tempScreen); delete []viewIconPosition; delete []viewIconLine; }; // ---------------------------------------------------------------- void View::change_zoom (int up_down) { position pos; Vector input, output; pos = projection_on_plan (viewed_point, eye_plan); // projected on eye_plan input = Vector (pos.x, pos.y, pos.z); output = rotation_matrix * input; // rotation -> (Oxy) plane if (up_down) { tx = (int)((double)tx+zoom*output.x()*(1-1/1.1)); ty = (int)((double)ty+zoom*output.y()*(1-1/1.1)); zoom = zoom/1.1; } else { zoom = zoom*1.1; tx = (int)((double)tx-zoom*output.x()*0.1); ty = (int)((double)ty-zoom*output.y()*0.1); } }; // ---------------------------------------------------------------- position View::get_real_coords (position_plan pos) { #ifdef TRACE5 printf ("get_real_coords\n"); #endif Vector output; Vector input; Vector2 temp1, temp2; position ret_pos; Matrix2 inverse_alpha_matrix; inverse_alpha_matrix = inverse(alpha_matrix); temp1 = Vector2 ((double)pos.x-(double)tx, (double)pos.y-(double)ty); temp2 = inverse_alpha_matrix*temp1; input = Vector (temp2.x()/zoom, temp2.y()/zoom, 0); output = inverse_rotation_matrix*input; ret_pos.x = output.x (); ret_pos.y = output.y (); ret_pos.z = output.z (); ret_pos = projection_on_plan (ret_pos, work_plan); return ret_pos; }; // ---------------------------------------------------------------- position_plan_double View::get_view_coords (position pos) { Vector output; Vector input; Vector2 temp1, temp2; position_plan_double ret; pos = projection_on_plan (pos, eye_plan); // projected on eye_plan input = Vector (pos.x, pos.y, pos.z); output = rotation_matrix * input; // rotation -> (Oxy) plane temp1 = Vector2 (output.x(), output.y()); temp1 = zoom*temp1; temp2 = alpha_matrix*temp1; ret.x = temp2.x()+tx; ret.y = temp2.y()+ty; return ret; } // ---------------------------------------------------------------- void View::set_tx_ty_with_vp (void) { Vector output; Vector input; Vector2 temp1, temp2; int rx, ry; position pos; pos = projection_on_plan (viewed_point, eye_plan); // projected on eye_plan input = Vector (pos.x, pos.y, pos.z); output = rotation_matrix * input; // rotation -> (Oxy) plane temp1 = Vector2 (output.x(), output.y()); temp1 = zoom*temp1; temp2 = alpha_matrix*temp1; rx = (int)(temp2.x()); ry = (int)(temp2.y()); tx = (int)(((int)width-20)/2-rx); ty = (int)(((int)height-170)/2-ry); tx0 = tx; ty0 = ty; } // ---------------------------------------------------------------- void View::displayViewIcon () { int i; displayViewIconLine (viewIconPosition[viewIconLine[12].p1], viewIconPosition[viewIconLine[12].p2], White, 'y', 12); displayViewIconLine (viewIconPosition[viewIconLine[13].p1], viewIconPosition[viewIconLine[13].p2], White, 'z', 13); displayViewIconLine (viewIconPosition[viewIconLine[14].p1], viewIconPosition[viewIconLine[14].p2], White, 'x', 14); for (i=0; i<12; i++) { displayViewIconLine (viewIconPosition[viewIconLine[i].p1], viewIconPosition[viewIconLine[i].p2], Green, 0, i); } } // ---------------------------------------------------------------- void View::displayViewIconLine (position p1, position p2, unsigned int col, char c, unsigned int index) { position_plan pp1, pp2, m1, m2; int tx1, ty1; double zoom1; if (c != 0) { m1.x = mx[index+18]; m1.y = my[index+18]; drawViewIconAxe (m1, c, Black); } tx1 = tx; ty1 = ty; zoom1 = zoom; zoom = viewIconZoom; tx = 0; /* viewIconTx; */ ty = 0; /* viewIconTy; */ pp1 = double_to_int (get_view_coords (p1)); pp2 = double_to_int (get_view_coords (p2)); pp1.x = (int)((double)pp1.x*0.28+viewIconTx); pp1.y = (int)((double)pp1.y*0.28+viewIconTy); pp2.x = (int)((double)pp2.x*0.28+viewIconTx); pp2.y = (int)((double)pp2.y*0.28+viewIconTy); zoom = zoom1; tx = tx1; ty = ty1; m1.x = mx[2*index]; m1.y = my[2*index]; m2.x = mx[2*index+1]; m2.y = my[2*index+1]; drawViewIconLine (m1, m2, Black); drawViewIconLine (pp1, pp2, col); mx[2*index] = pp1.x; my[2*index] = pp1.y; mx[2*index+1] = pp2.x; my[2*index+1] = pp2.y; if (c != 0) { drawViewIconAxe (pp2, c, Gold); mx[index+18] = pp2.x; my[index+18] = pp2.y; } } void View::drawViewIconLine (position_plan p1, position_plan p2, unsigned int col) { XSetForeground (display, gc, color[col]); XSetLineAttributes (display, gc, 1, LineSolid, CapProjecting, JoinMiter); XDrawLine (display, iconWin, gc, p1.x, p1.y,p2.x, p2.y); } void View::drawViewIconAxe (position_plan p, char c, unsigned int col) { char ch[2]; XTextItem textItem; XSetForeground (display, gc, color[col]); ch[0] = c; ch[1] = '\0'; textItem.chars = ch; textItem.nchars = strlen (ch); textItem.delta = 1; textItem.font = fontInfo->fid; XDrawText (display, iconWin, gc, p.x, p.y, &textItem, 1); } // ---------------------------------------------------------------- void View::print () { printf ("-------------------------------------------------------------------\n"); printf ("Mode: "); printf ("PERSPECTIV_MODE\n"); printf ("viewed_point: (%9.3f %9.3f %9.3f)\n", viewed_point.x, viewed_point.y, viewed_point.z); printf ("org: (%9.3f %9.3f %9.3f)\n", org.x, org.y, org.z); printf ("viewed_direction: (%9.3f %9.3f %9.3f)\n", viewed_direction.dx, viewed_direction.dy, viewed_direction.dz); printf ("zoom: %9.6f\n", zoom); printf ("eye_plan: (%9.3f %9.3f %9.3f %9.3f)\n", eye_plan.a, eye_plan.b, eye_plan.c, eye_plan.d); printf ("work_plan: (%9.3f %9.3f %9.3f %9.3f)\n", work_plan.a, work_plan.b, work_plan.c, work_plan.d); printf ("teta: %15.15f \n", teta); printf ("phi: %15.15f \n", phi); printf ("alpha: %15.15f \n", alpha); rotation_matrix.display (); printf ("tx: %d\n", tx); printf ("ty: %d\n", ty); printf ("tx0: %d\n", tx0); printf ("ty0: %d\n", ty0); { printf ("1 - viewed_direction: (%9.3f %9.3f %9.3f)\n", viewed_direction.dx, viewed_direction.dy, viewed_direction.dz); printf ("2 - viewed_direction: (%9.3f %9.3f %9.3f)\n", cos(phi)*cos(teta), sin(phi), cos(phi)*sin(teta)); Vector vd, res; vd = Vector (viewed_direction.dx, viewed_direction.dy, viewed_direction.dz); res = rotation_matrix*vd; res.display (); } printf ("-------------------------------------------------------------------\n"); }; // ---------------------------------------------------------------- void View::translate_view (type_tr_dir tr_dir) { switch (tr_dir) { case UP: ty+=20; break; case RIGHT: tx-=20; break; case LEFT: tx+=20; break; case DOWN: ty-=20; break; default: break; } } void View::translate (int dx, int dy) { tx = tx+dx; ty = ty+dy; } void View::setTxTy (int newTx, int newTy) { tx = newTx; ty = newTy; } void View::setViewCut (int newZCut, double newTetaCut, double newPhiCut) { zCut = newZCut; tetaCut = newTetaCut; phiCut = newPhiCut; } // ---------------------------------------------------------------- void View::recenter (void) { double norm; tx = tx0; ty = ty0; zoom = zoom0; alpha = alpha0; alpha_matrix = Matrix2 (cos(alpha), sin(alpha), -sin(alpha), cos(alpha)); teta = teta0; phi = phi0; norm = get_norm (viewed_point.x-org.x, viewed_point.y-org.y, viewed_point.z-org.z); viewed_direction.dx = cos(phi)*cos(teta); viewed_direction.dy = -sin(phi); viewed_direction.dz = cos(phi)*sin(teta); org.x = -viewed_direction.dx*norm + viewed_point.x; org.y = -viewed_direction.dy*norm + viewed_point.y; org.z = -viewed_direction.dz*norm + viewed_point.z; settings_2 (); // set all others parameters } // ---------------------------------------------------------------- void View::memorize (void) { tx0 = tx; ty0 = ty; zoom0 = zoom; teta0 = teta; phi0 = phi; alpha0 = alpha; } // ---------------------------------------------------------------- void View::set_all_with_new_teta_phi (void); // ---------------------------------------------------------------- void View::change_phi (int up_down) { double norm; norm = get_norm (viewed_point.x-org.x, viewed_point.y-org.y, viewed_point.z-org.z); if (up_down) phi+=M_PI/ROTATION_SPEED ; else phi-=M_PI/ROTATION_SPEED ; if (phi>M_PI/2) phi=M_PI/2; else if (phi<-M_PI/2) phi=-M_PI/2; viewed_direction.dx = cos(phi)*cos(teta); viewed_direction.dy = -sin(phi); viewed_direction.dz = cos(phi)*sin(teta); org.x = -viewed_direction.dx*norm + viewed_point.x; org.y = -viewed_direction.dy*norm + viewed_point.y; org.z = -viewed_direction.dz*norm + viewed_point.z; settings_2 (); // set all others parameters } // ---------------------------------------------------------------- void View::change_teta (int up_down) { double norm; norm = get_norm (viewed_point.x-org.x, viewed_point.y-org.y, viewed_point.z-org.z); if (up_down) teta+=M_PI/ROTATION_SPEED; else teta-=M_PI/ROTATION_SPEED; if (teta>M_PI) teta-=2*M_PI; else if (teta<-M_PI) teta+=2*M_PI; viewed_direction.dx = cos(phi)*cos(teta); viewed_direction.dy = -sin(phi); viewed_direction.dz = cos(phi)*sin(teta); org.x = -viewed_direction.dx*norm + viewed_point.x; org.y = -viewed_direction.dy*norm + viewed_point.y; org.z = -viewed_direction.dz*norm + viewed_point.z; settings_2 (); // set all others parameters } // ---------------------------------------------------------------- void View::change_alpha (int up_down) { if (up_down) alpha+=M_PI/ROTATION_SPEED; else alpha-=M_PI/ROTATION_SPEED; if (alpha>M_PI) alpha-=2*M_PI; else if (alpha<-M_PI) alpha+=2*M_PI; alpha_matrix = Matrix2 (cos(alpha), sin(alpha), -sin(alpha), cos(alpha)); } void View::set_alpha (double newAlpha) { alpha = newAlpha; alpha_matrix = Matrix2 (cos(alpha), sin(alpha), -sin(alpha), cos(alpha)); } // ---------------------------------------------------------------- void View::changeZCut (int up_down) { if (up_down) { zCut = zCut + 1; } else { zCut = zCut - 1; } } // ---------------------------------------------------------------- void View::changeTetaCut (int up_down) { if (up_down) tetaCut+=M_PI/18; else tetaCut-=M_PI/18; if (tetaCut>M_PI) tetaCut-=2*M_PI; else if (tetaCut<-M_PI) tetaCut+=2*M_PI; } // ---------------------------------------------------------------- void View::changePhiCut (int up_down) { if (up_down) phiCut+=M_PI/18 ; else phiCut-=M_PI/18 ; if (phiCut>M_PI/2) phiCut=M_PI/2; else if (phiCut<-M_PI/2) phiCut=-M_PI/2; } // ---------------------------------------------------------------- void View::up_down () { double norm; norm = get_norm (viewed_point.x-org.x, viewed_point.y-org.y, viewed_point.z-org.z); phi = -phi; if (phi>M_PI/2) phi=M_PI/2; else if (phi<-M_PI/2) phi=-M_PI/2; viewed_direction.dx = cos(phi)*cos(teta); viewed_direction.dy = -sin(phi); viewed_direction.dz = cos(phi)*sin(teta); org.x = -viewed_direction.dx*norm + viewed_point.x; org.y = -viewed_direction.dy*norm + viewed_point.y; org.z = -viewed_direction.dz*norm + viewed_point.z; settings_2 (); // set all others parameters alpha = alpha + M_PI; if (alpha>M_PI) alpha-=2*M_PI; else if (alpha<-M_PI) alpha+=2*M_PI; alpha_matrix = Matrix2 (cos(alpha), sin(alpha), -sin(alpha), cos(alpha)); } // ---------------------------------------------------------------- void View::adjust_teta_phi (void) { if (phi>M_PI/2) { phi = M_PI-phi; if (teta>0) teta = teta-M_PI; else teta = teta+M_PI; } else if (phi<-M_PI/2) { phi = -M_PI-phi; if (teta>0) teta = teta-M_PI; else teta = teta+M_PI; } } // ---------------------------------------------------------------- double View::get_teta () { return teta; } // ---------------------------------------------------------------- double View::get_phi () { return phi; } // ---------------------------------------------------------------- double View::get_alpha () { return alpha; } // ---------------------------------------------------------------- double View::get_zoom () { return zoom; } int View::get_tx () { return tx; } int View::get_ty () { return ty; } int View::getZCut () { return zCut; } double View::getTetaCut () { return tetaCut; } double View::getPhiCut () { return phiCut; } // ---------------------------------------------------------------- position View::get_org () { return org; } void View::drawLine (double x1, double y1, double x2, double y2) { double new_x1, new_y1, new_x2, new_y2; double a,b; double swap; if (x1>x2) { swap = x1; x1 = x2; x2 = swap; swap = y1; y1 = y2; y2 = swap; } else if (x1==x2) { if (y1>y2) { swap = x1; x1 = x2; x2 = swap; swap = y1; y1 = y2; y2 = swap; } } if ((maxim (x1,x2)<0) || (maxim (y1,y2)<0) || (minim (x1,x2)>width) || (minim (y1,y2)>height)) { /* line not in window */ } else { new_x1 = x1; new_y1 = y1; new_x2 = x2; new_y2 = y2; if ((x1 != x2) && (y1 != y2)) { a = ((double)y2-(double)y1)/((double)x2-(double)x1); b = (double)y2-a*(double)x2; if (x1<0) { new_x1 = 0; new_y1 = b; } if (x2>width) { new_x2 = width; new_y2 = a*new_x2+b; } if (new_y1<0) { new_y1 = 0; new_x1 = -b/a; } else if (new_y1>height) { new_y1 = height; new_x1 = (new_y1-b)/a; } if (new_y2<0) { new_y2 = 0; new_x2 = -b/a; } else if (new_y2>height) { new_y2 = height; new_x2 = (new_y2-b)/a; } } else if (x1 == x2) { new_x1 = (double)x1; if (y1<0) new_y1 = 0; new_x2 = (double)x2; if (y2>height) new_y2 = (double)height; } else if (y1 == y2) { if (x1<0) new_x1 = 0; new_y1 = (double)y1; if (x2>width) new_x2 = (double)width; new_y2 = (double)y2; } XDrawLine (display, tempScreen, gc, (unsigned int)new_x1, (unsigned int)new_y1, (unsigned int)new_x2, (unsigned int)new_y2); } } void View::drawNet(int alreadyComputed, int isCut) { int i,j,k,x,y,z; int ka,kb; int size; int halfSize; typeOfCell cellType; position org, xAxe, yAxe, zAxe; position_plan_double p1, p2; position a1Cut, a2Cut, a3Cut, a4Cut; position_plan_double a1, a2, a3, a4; double a, b, c; /* equation du plan de coupe: ax+by+cz-zCut = 0 */ char dashList[2]; dashList[0] = 3; dashList[1] = 3; a=0; /* needed by g++ -O2 */ b=0; /* needed by g++ -O2 */ c=0; /* needed by g++ -O2 */ if (alreadyComputed) { /* on reaffiche juste la Pixmap */ displayTempScreen (); } else { /* on recalcule l'image */ // computeCubeDatas (); size = anArchitecture->getSize(); halfSize = (int)(size/2); org = init_position (); /* org: sommet du cube */ org.x = -halfSize; if (anArchitecture->simuType == cubic) { org.y = size; } else { /* hexa */ org.y = size*hexaRoundSize; } org.z = -halfSize; xAxe = org; yAxe = org; zAxe = org; xAxe.x = halfSize; yAxe.y = 0; zAxe.z = halfSize; clearTempScreen (); if (isCut) { if (anArchitecture->simuType == cubic) { a = cos(phiCut)*sin(tetaCut); c = cos(phiCut)*cos(tetaCut); b = sin(phiCut); } else { a = cos(phiCut)*sin(tetaCut); c = cos(phiCut)*cos(tetaCut); b = sin(phiCut)/hexaRoundSize; } } XSetForeground (display, gc, color[White]); p1 = get_view_coords (org); /* sommet origine */ if (get_phi() > 0) { kb = 0; ka = +1; } else { kb = size - 1; ka = -1; } if (get_teta () <= -M_PI/2) { /* -180 < teta < -90 */ if (showAxes) { XSetForeground (display, gc, color[White]); p2 = get_view_coords (xAxe); drawLine (p1.x, p1.y, p2.x, p2.y); p2 = get_view_coords (yAxe); drawLine (p1.x, p1.y, p2.x, p2.y); p2 = get_view_coords (zAxe); drawLine (p1.x, p1.y, p2.x, p2.y); } for (k=0;kgetCellWithChecking (x, y, z); if ((!isCut) || ((isCut) && (a*x+b*y+c*z >= zCut))) { if (cellType != EMPTY) { if (simuType == cubic) putCube (cellType, x, y, z); else if (simuType == hexa) putHexa (cellType, x, y, z); } } } } else if (get_teta () <= 0) { /* -90 < teta < 0 */ if (showAxes) { XSetForeground (display, gc, color[White]); p2 = get_view_coords (xAxe); drawLine (p1.x, p1.y, p2.x, p2.y); p2 = get_view_coords (yAxe); drawLine (p1.x, p1.y, p2.x, p2.y); } for (k=0;k=0;i--) { x = i; y = j; z = kb + ka * k; cellType = anArchitecture->getCellWithChecking (x, y, z); if ((!isCut) || ((isCut) && (a*x+b*y+c*z >= zCut))) { if (cellType != EMPTY) { if (simuType == cubic) putCube (cellType, x, y, z); else if (simuType == hexa) putHexa (cellType, x, y, z); } } } if (showAxes) { XSetForeground (display, gc, color[White]); p2 = get_view_coords (zAxe); drawLine (p1.x, p1.y, p2.x, p2.y); } } else if (get_teta () <= M_PI/2) { /* 0 < teta < 90 */ for (k=0;k=0;j--) for (i=size-1;i>=0;i--) { x = i; y = j; z = kb + ka * k; cellType = anArchitecture->getCellWithChecking (x, y, z); if ((!isCut) || ((isCut) && (a*x+b*y+c*z >= zCut))) { if (cellType != EMPTY) { if (simuType == cubic) putCube (cellType, x, y, z); else if (simuType == hexa) putHexa (cellType, x, y, z); } } } if (showAxes) { XSetForeground (display, gc, color[White]); p2 = get_view_coords (xAxe); drawLine (p1.x, p1.y, p2.x, p2.y); p2 = get_view_coords (yAxe); drawLine (p1.x, p1.y, p2.x, p2.y); p2 = get_view_coords (zAxe); drawLine (p1.x, p1.y, p2.x, p2.y); } } else { /* 90 < teta < 180 */ if (showAxes) { XSetForeground (display, gc, color[White]); p2 = get_view_coords (xAxe); drawLine (p1.x, p1.y, p2.x, p2.y); p2 = get_view_coords (zAxe); drawLine (p1.x, p1.y, p2.x, p2.y); } for (k=0;k=0;j--) for (i=0;igetCellWithChecking (x, y, z); if ((!isCut) || ((isCut) && (a*x+b*y+c*z >= zCut))) { if (cellType != EMPTY) { if (simuType == cubic) putCube (cellType, x, y, z); else if (simuType == hexa) putHexa (cellType, x, y, z); } } } if (showAxes) { XSetForeground (display, gc, color[White]); p2 = get_view_coords (yAxe); drawLine (p1.x, p1.y, p2.x, p2.y); } } // x = (double)i-int(anArchitecture->getSize()/2); // z = (double)j-int(anArchitecture->getSize()/2); // y = (double)k; /* les points a1Cut, a2Cut, a3Cut et a4Cut sont les sommets du plan de coupe qui doit ici verifier l'equation: a.(x+size/2)+b.(z+size/2)+c.y=zCut et non plus l'equation ax+by+cz=zCut a cause des decalages pour se remettre d'accord avec la norme "theraulaz" */ if (isCut) { if ((a > 0.01) || (a < -0.01)) { /* a != 0 */ /* a1Cut */ setCut (&a1Cut, 0.0, -(double)halfSize, a, b, c); /* a2Cut */ setCut (&a2Cut, 0.0, (double)halfSize, a, b, c); /* a3Cut */ setCut (&a3Cut, (double)size, (double)halfSize, a, b, c); /* a4Cut */ setCut (&a4Cut, (double)size, -(double)halfSize, a, b, c); } else if ((b > 0.01) || (b < -0.01)) { /* b != 0 */ /* l'equation est alors: b.(z+size/2)+c.y=zCut */ a1Cut.x = (double)halfSize; a1Cut.y = 0.0; a1Cut.z = (zCut-c*a1Cut.y)/b-(double)halfSize; a2Cut.x = (double)halfSize; a2Cut.y = (double)size; a2Cut.z = (zCut-c*a2Cut.y)/b-(double)halfSize; a3Cut.x = 0.0; a3Cut.y = (double)size; a3Cut.z = (zCut-c*a3Cut.y)/b-(double)halfSize; a4Cut.x = 0.0; a4Cut.y = 0.0; a4Cut.z = (zCut-c*a4Cut.y)/b-(double)halfSize; } else { /* l'equation est alors: c.y=zCut */ a1Cut.x = (double)halfSize; a1Cut.z = (double)halfSize; a1Cut.y = zCut/c; a2Cut.x = -(double)halfSize; a2Cut.z = (double)halfSize; a2Cut.y = zCut/c; a3Cut.x = -(double)halfSize; a3Cut.z = -(double)halfSize; a3Cut.y = zCut/c; a4Cut.x = (double)halfSize; a4Cut.z = -(double)halfSize; a4Cut.y = zCut/c; } /* c'est parti pour l'affichage du plan de coupe*/ a1 = get_view_coords (a1Cut); a2 = get_view_coords (a2Cut); a3 = get_view_coords (a3Cut); a4 = get_view_coords (a4Cut); XSetForeground (display, gc, color[Blue]); XSetLineAttributes (display, gc, 1, LineDoubleDash, CapButt, JoinRound); XSetDashes (display, gc, 0, dashList, 2); drawLine (a1.x, a1.y, a2.x, a2.y); drawLine (a2.x, a2.y, a3.x, a3.y); drawLine (a3.x, a3.y, a4.x, a4.y); drawLine (a4.x, a4.y, a1.x, a1.y); } } } /* methode permettant de calculer les 4 sommets du plan de coupe rappel: equation a.(x+size/2)+b.(z+size/2)+c.y=zCut */ void View::setCut (position* aPosition, double aY, double aZ, double a, double b, double c) { position* p; int zNok; int size, halfSize; size = anArchitecture->getSize(); /* taille du cube de base */ halfSize = (int)(size/2); p = aPosition; zNok = 1; p->y = aY; p->z = aZ; p->x = (zCut-b*(p->z+(double)halfSize)-c*p->y)/a-(double)halfSize; /* si x n'est pas dans le cube, on recalcule avec z */ if ((p->x > (double)halfSize) && (b != 0)) { zNok = 0; /* il faudra aussi verifier que z soit dans le cube */ p->x = (double)halfSize; p->y = aY; p->z = (zCut-a*(p->x+(double)halfSize)-c*p->y)/b-(double)halfSize; } else if ((p->x < -(double)halfSize) && (b != 0)) { zNok = 0; /* il faudra aussi verifier que z soit dans le cube */ p->x = -(double)halfSize; p->y = aY; p->z = (zCut-a*(p->x+(double)halfSize)-c*p->y)/b-(double)halfSize; } /* on verifie que z est dans le cube */ if (zNok == 0) { if ((p->z > (double)halfSize) && (c != 0)) { p->y = aY; p->z = (double)halfSize; p->x = (zCut-b*(p->z+(double)halfSize)-c*p->y)/a-(double)halfSize; } else if ((p->z < -(double)halfSize) && (c != 0)) { p->y = aY; p->z = -(double)halfSize; p->x = (zCut-b*(p->z+(double)halfSize)-c*p->y)/a-(double)halfSize; } } } void View::drawFacette (Facette aFacette, typeOfCell cellType) { XPoint pt[aFacette.nbPoints+1]; int i; position_plan_double proj; position pos; Vector normalVector; /* USELESS double lightTeta, lightPhi; */ colorType border; int cx, cy, cz; normalVector = aFacette.getNormalVector (); if ((viewed_direction.dx*normalVector.x ()) + (viewed_direction.dy*normalVector.y ()) + (viewed_direction.dz*normalVector.z ()) < 0) { /* Facette non vue */ } else { /* Facette vue */ /* les coefficients cx, cy et cz representent l'orientation de la facette. On les arrondit en entiers pour les traiter plus facilement dans la suite */ if (normalVector.x()>=0) cx = (int)(normalVector.x()*10+0.1); else cx = (int)(normalVector.x()*10-0.1); if (normalVector.y()>=0) cy = (int)(normalVector.y()*10+0.1); else cy = (int)(normalVector.y()*10-0.1); if (normalVector.z()>=0) cz = (int)(normalVector.z()*10+0.1); else cz = (int)(normalVector.z()*10-0.1); if ((cz == 10) || (cz == -10)) { if (cellType == BLUE) { XSetForeground (display, gc, color[LightBlue]); border = MediumBlue; } else if (cellType == YELLOW) { XSetForeground (display, gc, color[Yellow]); border = DarkGoldenRod; } else if (cellType == RED) { XSetForeground (display, gc, color[Red]); border = Red4; } } else { if ((cx >= 8) || (cx <= -8)) { if (cz*cx >= 0) { if (cellType == BLUE) { XSetForeground (display, gc, color[Blue]); border = LightBlue; } else if (cellType == YELLOW) { XSetForeground (display, gc, color[GoldenRod]); border = Gold; } else if (cellType == RED) { XSetForeground (display, gc, color[Red3]); border = Red; } } else { if (cellType == BLUE) { XSetForeground (display, gc, color[HardBlue]); border = MediumBlue; } else if (cellType == YELLOW) { XSetForeground (display, gc, color[Gold]); border = DarkGoldenRod; } else if (cellType == RED) { XSetForeground (display, gc, color[Red2]); border = Red4; } } } else { /* cx = 0 */ if (cellType == BLUE) { XSetForeground (display, gc, color[MediumBlue]); border = LightBlue; } else if (cellType == YELLOW) { XSetForeground (display, gc, color[DarkGoldenRod]); border = Gold; } else if (cellType == RED) { XSetForeground (display, gc, color[Red4]); border = Red; } } } for (i=0; igetSize()/2); z = (double)j-int(anArchitecture->getSize()/2); y = (double)k; cubeCenter = setPosition (x+0.5, y+0.5, z+0.5); /* pour avoir l'affichage de boules */ /* proj = get_view_coords (cubeCenter); if (cellType == RED) { XSetForeground (display, gc, color[Red]); r = (int)(zoom*1.3); } else if (cellType == YELLOW) { XSetForeground (display, gc, color[Yellow]); r = (int)(zoom*1.1); } XFillArc (display, tempScreen, gc, (int)proj.x, (int)proj.y, r, r, 0, 360*64); if (cellType == RED) { XSetForeground (display, gc, color[Red3]); } else if (cellType == YELLOW) { XSetForeground (display, gc, color[GoldenRod]); } XDrawArc (display, tempScreen, gc, (int)proj.x, (int)proj.y, r, r, 0, 360*64); return; */ /* devant */ aFacette.set (cubeCenter, setPosition (x+1, y+1, z), setPosition (x+1, y+1, z+1), setPosition (x, y+1, z+1), setPosition (x, y+1, z)); drawFacette (aFacette, cellType); /* droite */ aFacette.set (cubeCenter, setPosition (x+1, y, z), setPosition (x+1, y, z+1), setPosition (x+1, y+1, z+1), setPosition (x+1, y+1, z)); drawFacette (aFacette, cellType); /* derriere */ aFacette.set (cubeCenter, setPosition (x, y, z), setPosition (x, y, z+1), setPosition (x+1, y, z+1), setPosition (x+1, y, z)); drawFacette (aFacette, cellType); /* gauche */ aFacette.set (cubeCenter, setPosition (x, y, z), setPosition (x, y, z+1), setPosition (x, y+1, z+1), setPosition (x, y+1, z)); drawFacette (aFacette, cellType); /* dessus */ aFacette.set (cubeCenter, setPosition (x, y, z+1), setPosition (x, y+1, z+1), setPosition (x+1, y+1, z+1), setPosition (x+1, y, z+1)); drawFacette (aFacette, cellType); /* dessous */ aFacette.set (cubeCenter, setPosition (x, y, z), setPosition (x, y+1, z), setPosition (x+1, y+1, z), setPosition (x+1, y, z)); drawFacette (aFacette, cellType); } /* Methode d'affichage d'une cellule hexagonale */ void View::putHexa (typeOfCell cellType, int i, int j, int k) { Facette aFacette; position hexaCenter; position upCenter; position downCenter; position facettePosition[6]; double x, y, z; Vector aVector; int nb; x = ((double)i-int(anArchitecture->getSize()/2))*zLenght; z = (double)j-int(anArchitecture->getSize()/2); y = ((double)k)*hexaRoundSize; if (i%2 == 0) { z = z+0.5; } hexaCenter = setPosition (x+0.5, y+hexaRoundSize/2, z+0.5); upCenter = setPosition (x+0.5, y+hexaRoundSize, z+0.5); downCenter = setPosition (x+0.5, y, z+0.5); for (nb=0; nb<6; nb++) { facettePosition[0] = setPosition (upCenter.x+hexaRoundSize*cos (nb*pi/3), upCenter.y, upCenter.z+hexaRoundSize*sin (nb*pi/3)); facettePosition[1] = setPosition (upCenter.x+hexaRoundSize*cos ((nb+1)*pi/3), upCenter.y, upCenter.z+hexaRoundSize*sin ((nb+1)*pi/3)); facettePosition[2] = setPosition (downCenter.x+hexaRoundSize*cos (nb*pi/3), downCenter.y, downCenter.z+hexaRoundSize*sin (nb*pi/3)); facettePosition[3] = setPosition (downCenter.x+hexaRoundSize*cos ((nb+1)*pi/3), downCenter.y, downCenter.z+hexaRoundSize*sin ((nb+1)*pi/3)); aFacette.set (hexaCenter, facettePosition[0], facettePosition[1], facettePosition[3], facettePosition[2]); drawFacette (aFacette, cellType); } for (nb=0; nb<6; nb++) { facettePosition[nb] = setPosition (upCenter.x+hexaRoundSize*cos (nb*pi/3), upCenter.y, upCenter.z+hexaRoundSize*sin (nb*pi/3)); } aFacette.set (hexaCenter, facettePosition[0], facettePosition[1], facettePosition[2], facettePosition[3], facettePosition[4], facettePosition[5]); drawFacette (aFacette, cellType); for (nb=0; nb<6; nb++) { facettePosition[nb] = setPosition (downCenter.x+hexaRoundSize*cos (nb*pi/3), downCenter.y, downCenter.z+hexaRoundSize*sin (nb*pi/3)); } aFacette.set (hexaCenter, facettePosition[0], facettePosition[1], facettePosition[2], facettePosition[3], facettePosition[4], facettePosition[5]); drawFacette (aFacette, cellType); } void View::computeFacetteDatas (Facette aFacette, int* facetteNb) { int i; position_plan_double proj; position pos; Vector normalVector; printf ("coucou\n"); normalVector = aFacette.getNormalVector (); if ((viewed_direction.dx*normalVector.x ()) + (viewed_direction.dy*normalVector.y ()) + (viewed_direction.dz*normalVector.z ()) < 0) { /* Facette non vue */ } else { /* Facette vue */ printf ("on est la\n"); if ((normalVector.z() > 0.5) || (normalVector.z() < -0.5)) { cubeFacetteColor[0][*facetteNb] = color[Red]; cubeFacetteColor[1][*facetteNb] = color[Gold]; } else { if ((normalVector.x() > 0.5) || (normalVector.x() < -0.5)) { cubeFacetteColor[0][*facetteNb] = color[Red3]; cubeFacetteColor[1][*facetteNb] = color[GoldenRod]; } else { cubeFacetteColor[0][*facetteNb] = color[Red4]; cubeFacetteColor[1][*facetteNb] = color[DarkGoldenRod]; } } printf ("et la\n"); for (i=0; igetSize()/2); z = (double)j-int(anArchitecture->getSize()/2); y = (double)k; cubeCenterDouble = get_view_coords (setPosition (x+0.5, y+0.5, z+0.5)); cubeCenter.x = (int)cubeCenterDouble.x; cubeCenter.y = (int)cubeCenterDouble.y; for (f=0; f<3; f++) { for (p=0; p<4; p++) { pt[p].x = cubeCenter.x + (cubePoint[f][p]).x; pt[p].y = cubeCenter.y + (cubePoint[f][p]).y; } pt[4] = pt[0]; XSetForeground (display, gc, cubeFacetteColor[(int)(cellType)-1][f]); XFillPolygon(display, tempScreen, gc, pt, 5, Convex, CoordModeOrigin); } } void View::clearTempScreen () { XSetForeground (display, gc, color[Black]); XFillRectangle (display, tempScreen, gc, 0, 0, width, height); } void View::displayTempScreen () { XCopyArea (display, tempScreen, win, gc, 0, 0, width, height, 0, 0); } Pixmap View::getTempScreen () { return tempScreen; } void View::setAxes () { showAxes = 1; } void View::unsetAxes () { showAxes = 0; } void View::resize () { int i, j, k; double minX, maxX, minY, maxY; double w, h, w1, h1, scale; double x, y, z; position cellCenter; position_plan_double cellCenterP; typeOfCell cellType; double size, halfSize; int decalage; decalage = 15; minX = 100000; minY = 100000; maxX = -100000; maxY = -100000; size = (double)anArchitecture->getSize(); halfSize = (double)(size/2); for (k=0;kgetCellWithChecking (i, j, k); if (cellType != EMPTY) { if (anArchitecture->simuType == cubic) { x = (double)i-halfSize; z = (double)j-halfSize; y = (double)k; cellCenter = setPosition (x+0.5, y+0.5, z+0.5); } else { x = ((double)i-halfSize)*zLenght; z = (double)j-halfSize; y = ((double)k)*hexaRoundSize; if (i%2 == 0) { z = z+0.5; } cellCenter = setPosition (x+0.5, y+hexaRoundSize/2, z+0.5); } cellCenterP = get_view_coords (cellCenter); if (cellCenterP.x < minX) minX = cellCenterP.x; if (cellCenterP.x > maxX) maxX = cellCenterP.x; if (cellCenterP.y < minY) minY = cellCenterP.y; if (cellCenterP.y > maxY) maxY = cellCenterP.y; } } position_plan_double center, edge; center = get_view_coords (setPosition (0, 0, 0)); edge = get_view_coords (setPosition (1, 1, 1)); minX = minX - abs ((int)edge.x - (int)center.x); maxX = maxX + abs ((int)edge.x - (int)center.x); minY = minY - abs ((int)edge.y - (int)center.y); maxY = maxY + abs ((int)edge.y - (int)center.y); w = width-decalage*2; h = height-decalage*2; w1 = maxX-minX; h1 = maxY-minY; if ((w1 <= 0) || (h1 <= 0)) { printf ("ERROR: unable to resize\n"); } else { scale = w/w1; if ((h/h1) < scale) scale = h/h1; zoom = zoom*scale; minX = 100000; minY = 100000; maxX = -100000; maxY = -100000; for (k=0;kgetCellWithChecking (i, j, k); if (cellType != EMPTY) { if (anArchitecture->simuType == cubic) { x = (double)i-halfSize; z = (double)j-halfSize; y = (double)k; cellCenter = setPosition (x+0.5, y+0.5, z+0.5); } else { x = ((double)i-halfSize)*zLenght; z = (double)j-halfSize; y = ((double)k)*hexaRoundSize; if (i%2 == 0) { z = z+0.5; } cellCenter = setPosition (x+0.5, y+hexaRoundSize/2, z+0.5); } cellCenterP = get_view_coords (cellCenter); if (cellCenterP.x < minX) minX = cellCenterP.x; if (cellCenterP.x > maxX) maxX = cellCenterP.x; if (cellCenterP.y < minY) minY = cellCenterP.y; if (cellCenterP.y > maxY) maxY = cellCenterP.y; } } tx = tx - (int)minX + (int)((w-maxX+minX)/2) + decalage; ty = ty - (int)minY + (int)((h-maxY+minY)/2) + decalage; } } void View::savePreview () { int i, j, k; double minX, maxX, minY, maxY; double w, h, w1, h1, scale; double x, y, z; position cellCenter; position_plan_double cellCenterP; typeOfCell cellType; double size, halfSize; int decalage; decalage = 15; minX = 100000; minY = 100000; maxX = -100000; maxY = -100000; size = (double)anArchitecture->getSize(); halfSize = (double)(size/2); for (k=0;kgetCellWithChecking (i, j, k); if (cellType != EMPTY) { if (anArchitecture->simuType == cubic) { x = (double)i-halfSize; z = (double)j-halfSize; y = (double)k; cellCenter = setPosition (x+0.5, y+0.5, z+0.5); } else { x = ((double)i-halfSize)*zLenght; z = (double)j-halfSize; y = ((double)k)*hexaRoundSize; if (i%2 == 0) { z = z+0.5; } cellCenter = setPosition (x+0.5, y+hexaRoundSize/2, z+0.5); } cellCenterP = get_view_coords (cellCenter); if (cellCenterP.x < minX) minX = cellCenterP.x; if (cellCenterP.x > maxX) maxX = cellCenterP.x; if (cellCenterP.y < minY) minY = cellCenterP.y; if (cellCenterP.y > maxY) maxY = cellCenterP.y; } } position_plan_double center, edge; center = get_view_coords (setPosition (0, 0, 0)); edge = get_view_coords (setPosition (1, 1, 1)); minX = minX - abs ((int)edge.x - (int)center.x); maxX = maxX + abs ((int)edge.x - (int)center.x); minY = minY - abs ((int)edge.y - (int)center.y); maxY = maxY + abs ((int)edge.y - (int)center.y); w = PIXMAP_WIDTH-decalage*2; h = PIXMAP_HEIGHT-decalage*2; w1 = maxX-minX; h1 = maxY-minY; if ((w1 <= 0) || (h1 <= 0)) { printf ("ERROR: unable to resize\n"); } else { scale = w/w1; if ((h/h1) < scale) scale = h/h1; zoom = zoom*scale; minX = 100000; minY = 100000; maxX = -100000; maxY = -100000; for (k=0;kgetCellWithChecking (i, j, k); if (cellType != EMPTY) { if (anArchitecture->simuType == cubic) { x = (double)i-halfSize; z = (double)j-halfSize; y = (double)k; cellCenter = setPosition (x+0.5, y+0.5, z+0.5); } else { x = ((double)i-halfSize)*zLenght; z = (double)j-halfSize; y = ((double)k)*hexaRoundSize; if (i%2 == 0) { z = z+0.5; } cellCenter = setPosition (x+0.5, y+hexaRoundSize/2, z+0.5); } cellCenterP = get_view_coords (cellCenter); if (cellCenterP.x < minX) minX = cellCenterP.x; if (cellCenterP.x > maxX) maxX = cellCenterP.x; if (cellCenterP.y < minY) minY = cellCenterP.y; if (cellCenterP.y > maxY) maxY = cellCenterP.y; } } tx = tx - (int)minX + (int)((w-maxX+minX)/2) + decalage; ty = ty - (int)minY + (int)((h-maxY+minY)/2) + decalage; drawNet (0, 0); } Pixmap aPixmap; /* USELESS unsigned int w2, h2; */ /* USELESS int hx, hy; */ aPixmap = XCreatePixmap (display, tempScreen, PIXMAP_WIDTH, PIXMAP_HEIGHT, depth); XCopyArea (display, tempScreen, aPixmap, gc, 0, 0, PIXMAP_WIDTH, PIXMAP_HEIGHT , 0, 0); XCopyArea (display, aPixmap, win, gc, 0, 0, PIXMAP_WIDTH, PIXMAP_HEIGHT , 200, 200); /* ok, j'ai le pixmap aPixmap */ if (anArchitecture->pixmapInitialized == BFalse) { anArchitecture->initializePixmap (display, previewWindow, depth); anArchitecture->setPixmap (display, aPixmap, gc); } } void View::setArchitecture (Architecture* anArch) { anArchitecture = anArch; }