diff --git a/Common/Context.h b/Common/Context.h index c9235a1079f30d7981c33b2489339844226f51fe..10f61f21510cc6ae81928edc906b186e87242d43 100644 --- a/Common/Context.h +++ b/Common/Context.h @@ -30,7 +30,8 @@ public : // general options char filename[256]; // the name of the currently opened file - char base_filename[256]; // the same without the extension + char no_ext_filename[256]; // the same without the extension + char base_filename[256]; // the base filename (no path, no extension) char *bgm_filename; // background mesh List_T *files; // all the files on the command line char *output_filename; // output file specified with command line option '-o' diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp index d02e5b7f012f46375084ec367d6bb74b3e2d24ee..211723cecd316f574000731431358212f9cf80d5 100644 --- a/Fltk/Callbacks.cpp +++ b/Fltk/Callbacks.cpp @@ -1,4 +1,4 @@ -// $Id: Callbacks.cpp,v 1.536 2007-08-03 00:44:28 geuzaine Exp $ +// $Id: Callbacks.cpp,v 1.537 2007-08-17 15:43:07 geuzaine Exp $ // // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle // @@ -4111,7 +4111,7 @@ void solver_cb(CALLBACK_ARGS) if(first[num]) { char file[256]; first[num] = 0; - strcpy(file, CTX.base_filename); + strcpy(file, CTX.no_ext_filename); strcat(file, SINFO[num].extension); WID->solver[num].input[0]->value(file); } diff --git a/Fltk/GUI_Projection.cpp b/Fltk/GUI_Projection.cpp index 2a25ab7b955f664ad792942296311b042c21da08..3d07e958d095d02636f77878348b71ecb4d42dc5 100644 --- a/Fltk/GUI_Projection.cpp +++ b/Fltk/GUI_Projection.cpp @@ -2,6 +2,7 @@ #include "Draw.h" #include "Options.h" #include "Context.h" +#include "OpenFile.h" #include "SelectBuffer.h" #include "GUI_Projection.h" #include "GUI_Extras.h" @@ -131,47 +132,71 @@ projection::projection(FProjectionFace *f, int x, int y, int w, int h, int BB, i group = new Fl_Scroll(x, y, w, h); SBoundingBox3d bounds = GMODEL->bounds(); FM::ProjectionSurface *ps = f->GetProjectionSurface(); - currentParams = new double[ps->GetNumParameters() + 9]; - for(int i = 0; i < ps->GetNumParameters() + 9; i++){ - Fl_Value_Input *v = new Fl_Value_Input(x, y + i * BH, BB, BH); - if(i < 3){ // scaling - currentParams[i] = 1.; - v->maximum(CTX.lc * 10.); - v->minimum(CTX.lc / 100.); - v->step(CTX.lc / 100.); - v->label((i == 0) ? "X scale" : (i == 1) ? "Y scale" : "Z scale"); - v->value(currentParams[i]); - } - else if(i < 6){ //rotation - currentParams[i] = 0.; - v->maximum(-180.); - v->minimum(180.); - v->step(0.1); - v->label((i == 3) ? "X rotation" : (i == 4) ? "Y rotation" : "Z rotation"); - v->value(currentParams[i]); - } - else if(i < 9){ // translation - currentParams[i] = bounds.center()[i - 6]; + + Fl_Toggle_Button *b = new Fl_Toggle_Button(x, y, BB, BH, "Set position"); + b->callback(set_position_cb, e); + + { // origin is stored in parameters[0,1,2] + SPoint3 pc = bounds.center(); + for(int i = 0; i < 3; i++){ + Fl_Value_Input *v = new Fl_Value_Input(x, y + (1 + i) * BH, BB, BH); + parameters.push_back(v); v->maximum(bounds.max()[i] + 10. * CTX.lc); v->minimum(bounds.min()[i] - 10. * CTX.lc); v->step(CTX.lc / 100.); - v->label((i == 6) ? "X translation" : (i == 7) ? "Y translation" : - "Z translation"); - v->value(currentParams[i]); + v->value(pc[i]); + v->label((i == 0) ? "X" : (i == 1) ? "Y" : "Z"); } - else{ // other parameters - currentParams[i] = ps->GetParameter(i - 9); - v->maximum(10. * CTX.lc); - v->minimum(-10. * CTX.lc); + ps->SetOrigin(pc[0], pc[1], pc[2]); + } + { // normal is stored in parameters[3,4,5] + Fl_Value_Input *v1 = new Fl_Value_Input(x, y + 4 * BH, BB / 3, BH); + parameters.push_back(v1); + v1->maximum(1.); v1->minimum(-1.); v1->step(0.01); v1->value(0.); + Fl_Value_Input *v2 = new Fl_Value_Input(x + BB / 3, y + 4 * BH, BB / 3, BH); + parameters.push_back(v2); + v2->maximum(1.); v2->minimum(-1.); v2->step(0.01); v2->value(0.); + Fl_Value_Input *v3 = new Fl_Value_Input(x + 2 * BB / 3, y + 4 * BH, BB - 2 * BB / 3, BH); + parameters.push_back(v3); + v3->maximum(1.); v3->minimum(-1.); v3->step(0.01); v3->value(1.); + v3->label("Normal"); + } + { // rotation is stored in parameters[6] + Fl_Value_Input *v = new Fl_Value_Input(x, y + 5 * BH, BB, BH, "Rotation"); + v->maximum(-180.); + v->minimum(180.); + v->step(0.1); + v->value(0.); + parameters.push_back(v); + } + { // scale is stored in parameters[7,8,9] + for(int i = 0; i < 3; i++){ + Fl_Value_Input *v = new Fl_Value_Input(x, y + (6 + i) * BH, BB, BH); + parameters.push_back(v); + v->maximum(CTX.lc * 10.); + v->minimum(CTX.lc / 100.); v->step(CTX.lc / 100.); - v->label(strdup(ps->GetLabel(i - 9).c_str())); - v->value(currentParams[i]); + v->value(CTX.lc / 10.); + v->label((i == 0) ? "Scale0" : (i == 1) ? "Scale1" : "Scale2"); } - ps->SetOrigin(currentParams[6], currentParams[7], currentParams[8]); - v->align(FL_ALIGN_RIGHT); - v->callback(update_cb, e); + } + + // other parameters are stored in parameters[10,...] + for(int i = 0; i < ps->GetNumParameters(); i++){ + Fl_Value_Input *v = new Fl_Value_Input(x, y + (9 + i) * BH, BB, BH); + v->maximum(10. * CTX.lc); + v->minimum(-10. * CTX.lc); + v->step(CTX.lc / 100.); + v->label(strdup(ps->GetLabel(i).c_str())); + v->value(ps->GetParameter(i)); parameters.push_back(v); } + + for(unsigned int i = 0; i < parameters.size(); i++){ + parameters[i]->align(FL_ALIGN_RIGHT); + parameters[i]->callback(update_cb, e); + } + group->end(); group->hide(); } @@ -180,22 +205,21 @@ projectionEditor::projectionEditor() { // construct GUI in terms of standard sizes const int BH = 2 * GetFontSize() + 1, BB = 7 * GetFontSize(), WB = 7; - const int width = (int)(3.5 * BB), height = 24 * BH; + const int width = (int)(3.75 * BB), height = 24 * BH; // create all widgets (we construct this once, we never deallocate!) _window = new Dialog_Window(width, height, "Reparameterize"); - new Fl_Box(WB, WB + BH, BB / 2, BH, "Select:"); + new Fl_Box(WB, WB + BH / 2, BB / 2, BH, "Select:"); Fl_Group *o = new Fl_Group(WB, WB, 2 * BB, 3 * BH); - _select[0] = - new Fl_Round_Button(2 * WB + BB / 2, WB, BB, BH, "Points"); - _select[0]->value(1); - _select[1] = - new Fl_Round_Button(2 * WB + BB / 2, WB + BH, BB, BH, "Elements"); - _select[2] = - new Fl_Round_Button(2 * WB + BB / 2, WB + 2 * BH, BB, BH, "Surfaces"); - for(int i = 0; i < 3; i++){ + _select[0] = new Fl_Round_Button(2 * WB + BB / 2, WB, BB, BH, "Points"); + _select[1] = new Fl_Round_Button(2 * WB + BB / 2, WB + BH, BB, BH, "Elements"); + if(GMODEL->numElements()) + _select[1]->value(1); + else + _select[0]->value(1); + for(int i = 0; i < 2; i++){ _select[i]->callback(select_cb, this); _select[i]->type(FL_RADIO_BUTTON); } @@ -210,16 +234,16 @@ projectionEditor::projectionEditor() b2->callback(save_selection_cb, this); } - const int brw = (int)(1.25 * BB); + const int brw = (int)(1.3 * BB); - _browser = new Fl_Hold_Browser(WB, 2 * WB + 3 * BH, brw, 5 * BH); + _browser = new Fl_Hold_Browser(WB, 2 * WB + 2 * BH, brw, 6 * BH); _browser->callback(browse_cb, this); _paramWin[0] = 2 * WB + brw; - _paramWin[1] = 2 * WB + 3 * BH; + _paramWin[1] = 2 * WB + 2 * BH; _paramWin[2] = width - 3 * WB - brw; - _paramWin[3] = 6 * BH; - _paramWin[4] = BB; + _paramWin[3] = 7 * BH; + _paramWin[4] = (int)(1.25 * BB); _paramWin[5] = BH; { @@ -233,43 +257,48 @@ projectionEditor::projectionEditor() int uvw = width - 2 * WB - 2 * hard - 3 * WB; int uvh = height - 8 * WB - 14 * BH - 2 * hard; - hardEdges[0] = new Fl_Toggle_Button(WB, 3 * WB + 9 * BH + hard, - hard, uvh); - hardEdges[1] = new Fl_Toggle_Button(width - 4 * WB - hard, 3 * WB + 9 * BH + hard, - hard, uvh); - hardEdges[2] = new Fl_Toggle_Button(WB + hard, 3 * WB + 9 * BH, - uvw, hard); - hardEdges[3] = new Fl_Toggle_Button(WB + hard, height - 5 * WB - 5 * BH - hard, - uvw, hard); + _hardEdges[0] = new Fl_Toggle_Button(WB, 3 * WB + 9 * BH + hard, + hard, uvh); + _hardEdges[1] = new Fl_Toggle_Button(width - 4 * WB - hard, 3 * WB + 9 * BH + hard, + hard, uvh); + _hardEdges[2] = new Fl_Toggle_Button(WB + hard, 3 * WB + 9 * BH, + uvw, hard); + _hardEdges[3] = new Fl_Toggle_Button(WB + hard, height - 5 * WB - 5 * BH - hard, + uvw, hard); for(int i = 0; i < 4; i++) - hardEdges[i]->tooltip("Push to mark edge as `hard'"); + _hardEdges[i]->tooltip("Push to mark edge as `hard'"); _uvPlot = new uvPlot(WB + hard, 3 * WB + 9 * BH + hard, uvw, uvh); _uvPlot->end(); - Fl_Slider *s = new Fl_Slider(width - 3 * WB, 3 * WB + 9 * BH + hard, 2 * WB, uvh); - s->minimum(1.); - s->maximum(0.); - s->value(1.); - s->callback(filter_cb, this); - s->tooltip("Filter selection by distance to projection surface"); + _slider = new Fl_Slider(width - 3 * WB, 3 * WB + 9 * BH + hard, 2 * WB, uvh); + _slider->minimum(1.); + _slider->maximum(0.); + _slider->value(1.); + _slider->callback(filter_cb, this); + _slider->tooltip("Filter selection by distance to projection surface"); + + _orientation = new Fl_Toggle_Button(width - 3 * WB, height - 5 * WB - 5 * BH - hard, + 2 * WB, hard); + _orientation->callback(filter_cb, this); + _orientation->tooltip("Filter elements using orientation"); - modes[0] = new Fl_Value_Input(WB, height - 4 * WB - 5 * BH, BB / 2, BH); - modes[0]->tooltip("Number of Fourier modes along u"); - modes[1] = new Fl_Value_Input(WB + BB / 2, height - 4 * WB - 5 * BH, BB / 2, BH, - "Fourier modes"); - modes[1]->tooltip("Number of Fourier modes along v"); - modes[2] = new Fl_Value_Input(WB, height - 4 * WB - 4 * BH, BB / 2, BH); - modes[2]->tooltip("Number of Chebyshev modes along u"); - modes[3] = new Fl_Value_Input(WB + BB / 2, height - 4 * WB - 4 * BH, BB / 2, BH, - "Chebyshev modes"); - modes[3]->tooltip("Number of Chebyshev modes along v"); + _modes[0] = new Fl_Value_Input(WB, height - 4 * WB - 5 * BH, BB / 2, BH); + _modes[0]->tooltip("Number of Fourier modes along u"); + _modes[1] = new Fl_Value_Input(WB + BB / 2, height - 4 * WB - 5 * BH, BB / 2, BH, + "Fourier modes"); + _modes[1]->tooltip("Number of Fourier modes along v"); + _modes[2] = new Fl_Value_Input(WB, height - 4 * WB - 4 * BH, BB / 2, BH); + _modes[2]->tooltip("Number of Chebyshev modes along u"); + _modes[3] = new Fl_Value_Input(WB + BB / 2, height - 4 * WB - 4 * BH, BB / 2, BH, + "Chebyshev modes"); + _modes[3]->tooltip("Number of Chebyshev modes along v"); for(int i = 0; i < 4; i++){ - modes[i]->value(8); - modes[i]->maximum(128); - modes[i]->minimum(1); - modes[i]->step(1); - modes[i]->align(FL_ALIGN_RIGHT); + _modes[i]->value(8); + _modes[i]->maximum(128); + _modes[i]->minimum(1); + _modes[i]->step(1); + _modes[i]->align(FL_ALIGN_RIGHT); } { @@ -337,9 +366,8 @@ int projectionEditor::getSelectionMode() { if(_select[0]->value()) return ENT_POINT; - else if(_select[2]->value()) - return ENT_SURFACE; - return ENT_ALL; + else + return ENT_ALL; } projection *projectionEditor::getCurrentProjection() @@ -391,6 +419,71 @@ void project_point(FM::ProjectionSurface *ps, double x, double y, double z, } } +void set_position_cb(Fl_Widget *w, void *data) +{ + projectionEditor *e = (projectionEditor*)data; + projection *p = e->getCurrentProjection(); + if(p){ + FM::ProjectionSurface *ps = p->face->GetProjectionSurface(); + std::vector<GVertex*> vertices; + std::vector<GEdge*> edges; + std::vector<GFace*> faces; + std::vector<GRegion*> regions; + std::vector<MElement*> elements; + char ib = SelectEntity(ENT_ALL, vertices, edges, faces, regions, elements); + if(ib == 'l'){ + if(vertices.size()){ + p->parameters[0]->value(vertices[0]->x()); + p->parameters[1]->value(vertices[0]->y()); + p->parameters[2]->value(vertices[0]->z()); + } + else if(elements.size()){ + SPoint3 pc = elements[0]->barycenter(); + p->parameters[0]->value(pc.x()); + p->parameters[1]->value(pc.y()); + p->parameters[2]->value(pc.z()); + if(elements[0]->getNumFaces()){ + MFace f = elements[0]->getFace(0); + SVector3 n = f.normal(); + p->parameters[3]->value(n[0]); + p->parameters[4]->value(n[1]); + p->parameters[5]->value(n[2]); + } + } + } + ((Fl_Toggle_Button*)w)->value(0); + } + update_cb(0, data); +} + +void getTangents(const SVector3 n, SVector3 &t1, SVector3 &t2, const double angle) +{ + SVector3 ex(0., 0., 0.); + if(n[0] == 0.) + ex[0] = 1.; + else if(n[1] == 0.) + ex[1] = 1.; + else + ex[2] = 1.; + SVector3 a = crossprod(n, ex); + a.normalize(); + SVector3 b = crossprod(n, a); + b.normalize(); + double x = n[0], y = n[1], z = n[2]; + double c = cos(angle * M_PI / 180.), s = sin(angle * M_PI / 180.); + double rot[3][3] = + {{x * x * (1-c) + c , x * y * (1-c) - z * s, x * z * (1-c) + y * s}, + {y * x * (1-c) + z * s, y * y * (1-c) + c , y * z * (1-c) - x * s}, + {x * z * (1-c) - y * s, y * z * (1-c) + x * s, z * z * (1-c) + c }}; + for(int i = 0; i < 3; i++){ + t1[i] = t2[i] = 0.; + for(int j = 0; j < 3; j++){ + t1[i] += rot[i][j] * a[j]; + t2[i] += rot[i][j] * b[j]; + } + } +} + void update_cb(Fl_Widget *w, void *data) { projectionEditor *e = (projectionEditor*)data; @@ -400,21 +493,26 @@ void update_cb(Fl_Widget *w, void *data) projection *p = e->getCurrentProjection(); if(p){ FM::ProjectionSurface *ps = p->face->GetProjectionSurface(); - ps->Rescale(p->parameters[0]->value() / p->currentParams[0], - p->parameters[1]->value() / p->currentParams[1], - p->parameters[2]->value() / p->currentParams[2]); - ps->Rotate(p->parameters[3]->value() - p->currentParams[3], - p->parameters[4]->value() - p->currentParams[4], - p->parameters[5]->value() - p->currentParams[5]); - ps->Translate(p->parameters[6]->value() - p->currentParams[6], - p->parameters[7]->value() - p->currentParams[7], - p->parameters[8]->value() - p->currentParams[8]); - for (int i = 0; i < 9; i++) - p->currentParams[i] = p->parameters[i]->value(); - for (int i = 9; i < 9 + ps->GetNumParameters(); i++) - ps->SetParameter(i - 9, p->parameters[i]->value()); - p->face->computeGraphicsRep(64, 64); // FIXME: hardcoded for now! - + ps->SetOrigin(p->parameters[0]->value(), + p->parameters[1]->value(), + p->parameters[2]->value()); + SVector3 n(p->parameters[3]->value(), + p->parameters[4]->value(), + p->parameters[5]->value()); + if(!n.normalize()) n[2] = 1.; + SVector3 t1, t2; + getTangents(n, t1, t2, p->parameters[6]->value()); + ps->SetE0(n[0], n[1], n[2]); + ps->SetE1(t1[0], t1[1], t1[2]); + ps->SetE2(t2[0], t2[1], t2[2]); + ps->SetScale(p->parameters[7]->value(), + p->parameters[8]->value(), + p->parameters[9]->value()); + for (int i = 0; i < ps->GetNumParameters(); i++) + ps->SetParameter(i, p->parameters[i + 10]->value()); + + p->face->computeGraphicsRep(64, 64); // FIXME: hardcoded for now + // project selected points and elements and update u,v display std::vector<double> u, v, dist; std::vector<std::complex<double> > f; @@ -544,13 +642,12 @@ void select_cb(Fl_Widget *w, void *data) void filter_cb(Fl_Widget *w, void *data) { - Fl_Slider *slider = (Fl_Slider*)w; projectionEditor *e = (projectionEditor*)data; projection *p = e->getCurrentProjection(); if(p){ SBoundingBox3d bbox = GMODEL->bounds(); double lc = norm(SVector3(bbox.max(), bbox.min())); - double threshold = slider->value() * lc; + double threshold = e->getThreshold() * lc; FM::ProjectionSurface *ps = p->face->GetProjectionSurface(); std::vector<GEntity*> &ent(e->getEntities()); for(unsigned int i = 0; i < ent.size(); i++){ @@ -575,8 +672,17 @@ void filter_cb(Fl_Widget *w, void *data) ps->F(uu, vv, p[0], p[1], p[2]); double dx = pc.x() - p[0], dy = pc.y() - p[1], dz = pc.z() - p[2]; if(uu >= 0. && uu <= 1. && vv >= 0. && vv < 1. && - sqrt(dx * dx + dy * dy + dz * dz) < threshold) + sqrt(dx * dx + dy * dy + dz * dz) < threshold){ ele[i]->setVisibility(2); + // keep only the elements oriented in the same direction as + // the projection surface + if(e->getOrientation() && ele[i]->getNumFaces()){ + MFace f = ele[i]->getFace(0); + SVector3 n = f.normal(), n2; + ps->GetNormal(uu, vv, n2[0], n2[1], n2[2]); + if(dot(n, n2) < 0.) ele[i]->setVisibility(1); + } + } else ele[i]->setVisibility(1); } @@ -600,21 +706,39 @@ void hide_cb(Fl_Widget *w, void *data) void save_selection_cb(Fl_Widget *w, void *data) { projectionEditor *e = (projectionEditor*)data; - std::vector<GEntity*> &ent(e->getEntities()); - if(file_chooser(0, 1, "Save Selection", "*.geo")){ + if(file_chooser(0, 1, "Save Selection", "*.{geo,msh}")){ FILE *fp = fopen(file_chooser_get_name(1), "w"); if(!fp){ Msg(GERROR, "Unable to open file `%s'", file_chooser_get_name(1)); return; } - // maybe we should save as mesh file + std::vector<GEntity*> &ent(e->getEntities()); for(unsigned int i = 0; i < ent.size(); i++){ GVertex *gv = dynamic_cast<GVertex*>(ent[i]); if(gv && gv->getSelection()) fprintf(fp, "Point(%d) = {%.16g,%.16g,%.16g,1};\n", gv->tag(), gv->x(), gv->y(), gv->z()); } - // deal with elements here + std::vector<MElement*> &ele(e->getElements()); + if(ele.size()){ + int nelm = 0; + std::set<MVertex*> verts; + for(unsigned int i = 0; i < ele.size(); i++){ + if(ele[i]->getVisibility() == 2){ + nelm++; + for(int j = 0; j < ele[i]->getNumVertices(); j++) + verts.insert(ele[i]->getVertex(j)); + } + } + fprintf(fp, "$NOD\n%d\n", verts.size()); + for(std::set<MVertex*>::iterator it = verts.begin(); it != verts.end(); it++) + (*it)->writeMSH(fp); + fprintf(fp, "$ENDNOD\n$ELM\n%d\n", nelm); + for(unsigned int i = 0; i < ele.size(); i++) + if(ele[i]->getVisibility() == 2) + ele[i]->writeMSH(fp, 1.0); + fprintf(fp, "$ENDELM\n"); + } fclose(fp); } } @@ -667,12 +791,15 @@ void save_projection_cb(Fl_Widget *w, void *data) if(p){ FM::ProjectionSurface *ps = p->face->GetProjectionSurface(); if(file_chooser(0, 1, "Save Projection", "*.pro")){ - FILE *fp = fopen(file_chooser_get_name(1), "w"); + char *name = file_chooser_get_name(1); + FILE *fp = fopen(name, "w"); if(!fp){ - Msg(GERROR, "Unable to open file `%s'", file_chooser_get_name(1)); + Msg(GERROR, "Unable to open file `%s'", name); return; } - fprintf(fp, "1\n%s\n%s\n", ps->GetName().c_str(), ps->GetName().c_str()); + char no_ext[256], ext[256], base[256]; + SplitFileName(name, no_ext, ext, base); + fprintf(fp, "1\n%s\n%s\n", base, ps->GetName().c_str()); for(unsigned int i = 0; i < p->parameters.size(); i++) fprintf(fp, "%.16g\n", p->parameters[i]->value()); fclose(fp); @@ -692,20 +819,20 @@ void compute_cb(Fl_Widget *w, void *data) e->uv()->get(u, v, dist, f); if(f.empty()) return; - int uModes = (int)e->modes[0]->value(); - int vModes = (int)e->modes[1]->value(); + int uModes = e->getMode(0); + int vModes = e->getMode(1); if(f.size() < uModes * vModes){ Msg(GERROR, "Number of points < uModes * vModes"); return; } - int uM = (int)e->modes[2]->value(); - int vM = (int)e->modes[3]->value(); - int h0 = e->hardEdges[0]->value(); - int h1 = e->hardEdges[1]->value(); - int h2 = e->hardEdges[2]->value(); - int h3 = e->hardEdges[3]->value(); + int uM = e->getMode(2); + int vM = e->getMode(3); + int h0 = e->getHardEdge(0); + int h1 = e->getHardEdge(1); + int h2 = e->getHardEdge(2); + int h3 = e->getHardEdge(3); // create the Fourier faces (with boundaries) FM::ProjectionSurface *ps = p->face->GetProjectionSurface(); diff --git a/Fltk/GUI_Projection.h b/Fltk/GUI_Projection.h index 74d3367f6f6943ef7ad3e7f16c3a638887e52a27..09c6fa04547d17ab94eea738a24b13294d05accf 100644 --- a/Fltk/GUI_Projection.h +++ b/Fltk/GUI_Projection.h @@ -17,6 +17,7 @@ void select_cb(Fl_Widget *w, void *data); void filter_cb(Fl_Widget *w, void *data); void browse_cb(Fl_Widget *w, void *data); +void set_position_cb(Fl_Widget *w, void *data); void update_cb(Fl_Widget *w, void *data); void close_cb(Fl_Widget *w, void *data); void hide_cb(Fl_Widget *w, void *data); @@ -49,7 +50,6 @@ class projection { public: FProjectionFace *face; Fl_Group *group; - double *currentParams; std::vector<Fl_Value_Input*> parameters; projection(FProjectionFace *f, int x, int y, int w, int h, int BB, int BH, projectionEditor *e); @@ -65,19 +65,24 @@ class projectionEditor { int _paramWin[6]; Fl_Round_Button *_select[3]; uvPlot *_uvPlot; + Fl_Value_Input *_modes[4]; + Fl_Toggle_Button *_hardEdges[4], *_orientation; + Fl_Slider *_slider; public: projectionEditor(); void load(FProjectionFace *face, std::string tag=""); void show(){ _window->show(); select_cb(0, this); } uvPlot *uv() { return _uvPlot; } - Fl_Value_Input* modes[4]; - Fl_Toggle_Button* hardEdges[4]; std::vector<MElement*> &getElements() { return _elements; } std::vector<GEntity*> &getEntities() { return _entities; } std::vector<projection*> &getProjections() { return _projections; } projection *getCurrentProjection(); projection *getLastProjection(); int getSelectionMode(); + int getMode(int i){ return (int)_modes[i]->value(); } + int getHardEdge(int i){ return (int)_hardEdges[i]->value(); } + int getOrientation(){ return (int)_orientation->value(); } + double getThreshold(){ return _slider->value(); } }; #endif diff --git a/Geo/GeoStringInterface.cpp b/Geo/GeoStringInterface.cpp index 60f173a7441b59e7d2cf801266fbb480f5194e11..a2a8f5a7451acdddc224f0bcf32e967c1db22f67 100644 --- a/Geo/GeoStringInterface.cpp +++ b/Geo/GeoStringInterface.cpp @@ -1,4 +1,4 @@ -// $Id: GeoStringInterface.cpp,v 1.8 2007-02-07 13:06:49 geuzaine Exp $ +// $Id: GeoStringInterface.cpp,v 1.9 2007-08-17 15:43:07 geuzaine Exp $ // // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle // @@ -109,8 +109,8 @@ void add_infile(char *text, char *fich, bool deleted_something) } if(!CTX.expert_mode) { - char base[256], ext[256]; - SplitFileName(fich, base, ext); + char no_ext[256], ext[256], base[256]; + SplitFileName(fich, no_ext, ext, base); if(strlen(ext) && strcmp(ext, ".geo") && strcmp(ext, ".GEO")){ char question[1024]; sprintf(question, diff --git a/Geo/MFace.h b/Geo/MFace.h index 524f7f8229f2636379550b7f0418b074599e5f6f..0503d97a2e100a04d3470e655dfa83175a79da3e 100644 --- a/Geo/MFace.h +++ b/Geo/MFace.h @@ -114,6 +114,17 @@ class MFace { _v[2]->x(), _v[2]->y(), _v[2]->z(), n); return SVector3(n[0], n[1], n[2]); } + SVector3 tangent(int num) const + { + SVector3 t0(_v[1]->x() - _v[0]->x(), + _v[1]->y() - _v[0]->y(), + _v[1]->z() - _v[0]->z()); + t0.normalize(); + if(!num) return t0; + SVector3 n = normal(); + SVector3 t1 = crossprod(n, t0); + return t1; + } SPoint3 barycenter() const { SPoint3 p(0., 0., 0.); diff --git a/Graphics/Geom.cpp b/Graphics/Geom.cpp index ef09cd3b0021a2f186df7ef9b4b43f3d1bb0d2c4..7f1fd4f63d06538a2146f4fd54973740f50d604b 100644 --- a/Graphics/Geom.cpp +++ b/Graphics/Geom.cpp @@ -1,4 +1,4 @@ -// $Id: Geom.cpp,v 1.135 2007-08-07 20:27:20 anand Exp $ +// $Id: Geom.cpp,v 1.136 2007-08-17 15:43:07 geuzaine Exp $ // // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle // @@ -286,6 +286,17 @@ class drawGFace { glEnd(); glDisable(GL_LIGHTING); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + if(CTX.geom.normals) { + GPoint p = f->point(0.5, 0.5); + SVector3 n = f->normal(SPoint2(0.5, 0.5)); + for(int i = 0; i < 3; i++) + n[i] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[i]; + glColor4ubv((GLubyte *) & CTX.color.geom.normals); + Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, + CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, + p.x(), p.y(), p.z(), n[0], n[1], n[2], CTX.geom.light); + } } void _drawPlaneGFace(GFace *f) diff --git a/Parser/CreateFile.cpp b/Parser/CreateFile.cpp index 614b3afbbe62c8c2c0d840f994e6e7890c9e1d3d..a2dea94a6ef5aeeb476f0da0c009048da5b266ca 100644 --- a/Parser/CreateFile.cpp +++ b/Parser/CreateFile.cpp @@ -1,4 +1,4 @@ -// $Id: CreateFile.cpp,v 1.17 2007-05-13 10:37:02 geuzaine Exp $ +// $Id: CreateFile.cpp,v 1.18 2007-08-17 15:43:07 geuzaine Exp $ // // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle // @@ -84,7 +84,7 @@ int GuessFileFormatFromFileName(char *name) void GetDefaultFileName(int format, char *name) { char ext[32] = ""; - strcpy(name, CTX.base_filename); + strcpy(name, CTX.no_ext_filename); switch(format){ case FORMAT_GEO: strcpy(ext, ".geo_unrolled"); break; case FORMAT_MSH: strcpy(ext, ".msh"); break; @@ -115,13 +115,15 @@ void GetDefaultFileName(int format, char *name) void CreateOutputFile(char *filename, int format) { - char name[256]; + char name[256], no_ext[256], ext[256], base[256]; if(!filename || !strlen(filename)) GetDefaultFileName(format, name); else strcpy(name, filename); + SplitFileName(name, no_ext, ext, base); + int oldformat = CTX.print.format; CTX.print.format = format; CTX.printing = 1; @@ -288,14 +290,14 @@ void CreateOutputFile(char *filename, int format) (CTX.print.eps_background ? GL2PS_DRAW_BACKGROUND : 0) | (CTX.print.eps_compress ? GL2PS_COMPRESS : 0) | (CTX.print.eps_ps3shading ? 0 : GL2PS_NO_PS3_SHADING); - + GLint buffsize = 0; int res = GL2PS_OVERFLOW; while(res == GL2PS_OVERFLOW) { buffsize += 2048 * 2048; gl2psBeginPage(CTX.base_filename, "Gmsh", viewport, psformat, pssort, psoptions, GL_RGBA, 0, NULL, - 15, 20, 10, buffsize, fp, name); + 15, 20, 10, buffsize, fp, base); if(CTX.print.eps_quality == 0){ double modelview[16], projection[16]; glGetDoublev(GL_PROJECTION_MATRIX, projection); @@ -337,7 +339,7 @@ void CreateOutputFile(char *filename, int format) buffsize += 2048 * 2048; gl2psBeginPage(CTX.base_filename, "Gmsh", viewport, GL2PS_TEX, GL2PS_NO_SORT, GL2PS_NONE, GL_RGBA, 0, NULL, - 0, 0, 0, buffsize, fp, name); + 0, 0, 0, buffsize, fp, base); PixelBuffer buffer(width, height, GL_RGB, GL_UNSIGNED_BYTE); int oldtext = CTX.print.text; CTX.print.text = 1; diff --git a/Parser/OpenFile.cpp b/Parser/OpenFile.cpp index e2f187b1ea0ffe68bec4f2f44fa361b828a5fdff..5220d7795ee667155ba4f09d0f5b233227019cbc 100644 --- a/Parser/OpenFile.cpp +++ b/Parser/OpenFile.cpp @@ -1,4 +1,4 @@ -// $Id: OpenFile.cpp,v 1.149 2007-07-11 16:38:36 geuzaine Exp $ +// $Id: OpenFile.cpp,v 1.150 2007-08-17 15:43:07 geuzaine Exp $ // // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle // @@ -72,14 +72,21 @@ void FixWindowsPath(char *in, char *out){ #endif } -void SplitFileName(char *name, char *base, char *ext) +void SplitFileName(char *name, char *no_ext, char *ext, char *base) { - strcpy(base, name); + strcpy(no_ext, name); strcpy(ext, ""); - for(int i = strlen(name)-1; i >= 0; i--){ + for(int i = strlen(name) - 1; i >= 0; i--){ if(name[i] == '.'){ strcpy(ext, &name[i]); - base[i] = '\0'; + no_ext[i] = '\0'; + break; + } + } + strcpy(base, no_ext); + for(int i = strlen(no_ext) - 1; i >= 0; i--){ + if(no_ext[i] == '/' || no_ext[i] == '\\'){ + strcpy(base, &no_ext[i + 1]); break; } } @@ -262,10 +269,11 @@ void ParseString(char *str) void SetProjectName(char *name) { - char base[356], ext[256]; - SplitFileName(name, base, ext); + char no_ext[256], ext[256], base[256]; + SplitFileName(name, no_ext, ext, base); strncpy(CTX.filename, name, 255); + strncpy(CTX.no_ext_filename, no_ext, 255); strncpy(CTX.base_filename, base, 255); #if defined(HAVE_FLTK) @@ -289,8 +297,8 @@ int MergeFile(char *name, int warn_if_missing) Msg(STATUS2, "Reading '%s'", name); - char ext[256], base[256]; - SplitFileName(name, base, ext); + char no_ext[256], ext[256], base[256]; + SplitFileName(name, no_ext, ext, base); #if defined(HAVE_FLTK) if(!CTX.batch) { @@ -300,12 +308,12 @@ int MergeFile(char *name, int warn_if_missing) if(fl_choice("File '%s' is in gzip format.\n\nDo you want to uncompress it?", "Cancel", "Uncompress", NULL, name)){ char tmp[256]; - sprintf(tmp, "gunzip -c %s > %s", name, base); + sprintf(tmp, "gunzip -c %s > %s", name, no_ext); if(SystemCall(tmp)) Msg(GERROR, "Failed to uncompress `%s': check directory permissions", name); if(!strcmp(CTX.filename, name)) // this is the project file - SetProjectName(base); - return MergeFile(base); + SetProjectName(no_ext); + return MergeFile(no_ext); } } } diff --git a/Parser/OpenFile.h b/Parser/OpenFile.h index db972d73e35524b0deaa75a56ed0cc0f6bd8460f..7ccd8368c1266dccd0f2b005bdd4288bea92c927 100644 --- a/Parser/OpenFile.h +++ b/Parser/OpenFile.h @@ -27,7 +27,7 @@ void OpenProjectMacFinder(const char *filename); int MergeFile(char *filename, int warn_if_missing=0); void FixRelativePath(char *in, char *out); void FixWindowsPath(char *in, char *out); -void SplitFileName(char *name, char *base, char *ext); +void SplitFileName(char *name, char *no_ext, char *ext, char *base); void SetBoundingBox(double xmin, double xmax, double ymin, double ymax, double zmin, double zmax);