bool CIRCLE_WIDGET::finish_literal(void) { MULTI_CMDptr cmd = new MULTI_CMD; // Get a mesh to put the new curve into. LMESHptr mesh = TEXBODY::get_skel_mesh(cmd); assert(mesh != 0); Wplane P = get_draw_plane(_literal_shape); int res_level = 3; int num_edges = 4; // XXX - default is 4 edges; should be smarter: // Create the curve Bcurve* curve = BcurveAction::create( mesh, _literal_shape, P.normal(), num_edges, res_level, 0, 0, cmd ); curve->mesh()->update_subdivision(res_level); // If the curve completes a closed loop (on its own or by // joining existing curves), fill the interior with a // "panel" surface: PanelAction::create(curve->extend_boundaries(), cmd); WORLD::add_command(cmd); return true; }
int CIRCLE_WIDGET::stroke_cb(CGESTUREptr& g, DrawState*&) { err_adv(debug_all, "CIRCLE_WIDGET::stroke_cb()"); // Activity occurred to extend the deadline for fading away: reset_timeout(); // sanity check assert(g); if( !g->is_line() ) return 1; _preview.update_length(); if (PIXEL_list(_preview).dist(g->start()) < PIXEL_DIST_THRESH || g->start().dist(_center) < PIXEL_DIST_THRESH ) { if ( _circle ) { Bcurve *border = Bcurve::lookup(_circle->bfaces().get_boundary().edges()); if ( border != 0 ) { Wplane plane = border->plane(); _radius = _center.dist(Wpt(plane, Wline(XYpt(g->end())))); } } else { Wplane P = get_draw_plane(g->end()); if (!P.is_valid()) return 1; _radius = _center.dist(Wpt(P, Wline(XYpt(g->end())))); } make_preview(); } return 1; }
void CIRCLE_WIDGET::make_preview( void ) { _preview.clear(); // Get a coordinate system Wvec Z = _plane.normal(); Wvec X = Z.perpend(); Wvec Y = cross(Z,X); Wtransf xf(_center, X, Y, Z); // Make the hi-res circle for the curve's map1d3d: const int ORIG_RES = 256; _preview.realloc(ORIG_RES + 1); double dt = (2*M_PI)/ORIG_RES; for (int i=0; i<ORIG_RES; i++) { double t = dt*i; _preview += xf*Wpt(_radius*cos(t), _radius*sin(t), 0); } _preview += _preview[0]; // make it closed if( _suggest_active ) { return; } if( _circle == 0 ) { // XXX - no undo! should fix _circle = PanelAction::create( _plane, _center, _radius, TEXBODY::get_skel_mesh(0), _disk_res, 0 ); } else { Bcurve *border = Bcurve::lookup(_circle->bfaces().get_boundary().edges()); if( border != 0 ) { Wpt_listMap *map = Wpt_listMap::upcast(border->map()); if( map ) map->set_pts(_preview); } } }
int DrawManip::move(CEvent &e, State *&s) { if (!_cmd) return 0; // XXX - needs work, doing plane constraint ATM... if (plane().is_valid()) { apply_translation(plane().intersect(ptr_ray()) - _down_pt); return 0; } // XXX - need comments... CRV_SKETCHptr cs = CRV_SKETCH::get_instance(); if (cs->is_active() & _down) { Bcurve* curve = cs->curve(); Wpt_listMap* map = cs->shadow_map(); Wpt pt = Wpt(curve->shadow_plane(), Wline(ptr_cur())); if (_first) map->set_p0(new WptMap(pt)); else map->set_p1(new WptMap(pt)); map->recompute(); SurfaceCurveMap* o = (SurfaceCurveMap*)curve->map(); Wpt first = o->map(0), last = o->map(1); if (curve->b1()) { curve->b1()->move_to(first); } if (curve->b2()) { curve->b2()->move_to(last); } cs->reset_timeout(); return 0; } return 0; }
bool SWEEP_DISK::build_box(CWpt& o, CWvec& t, CWpt_list& spts, MULTI_CMDptr cmd) { // Editing or Creating bool is_editing = !(_surfs.empty()); // get list of Bpoints around the boundary of the base surface: ARRAY<Bpoint*> bot_pts = is_editing ? _points.extract(_points.num()/2, _points.num()/2) : Bpoint::get_points(_boundary.verts()); assert ( bot_pts.num() > 2 ); int n = bot_pts.num(); Bpoint_list top_pts(n); // If surface normals of base surface point along the sweep // direction, they have to be reversed. otherwise, the // boundary runs CW, so we reverse the order of the bottom // points to get them to run CCW: // // XXX - needs fix to work on embedded region, similar to // build_tube() above. if ( _plane.normal()*t < 0 ) { if (!is_editing) bot_pts.reverse(); } else { reverse_faces( _enclosed_faces ); if(cmd) cmd->add(make_shared<REVERSE_FACES_CMD>(_enclosed_faces, true)); } double avg_len = _boundary.edges().avg_len(); if ( isZero(avg_len) ) { cerr << "SWEEP_DISK::build_box(): ERROR, boundary avg len is zero" << endl; return false; } int num_edges = max( (int)round( spts.length()/avg_len ), 1 ); int res_level = Config::get_var_int("BOX_RES_LEVEL", 2,true); // we'll keep lists of all curves and surfaces for the box, // for setting their res level uniformly: Bcurve_list curves = Bcurve::get_curves(_boundary.edges()); Bsurface_list surfaces = Bsurface::get_surfaces(_enclosed_faces); if (!surfaces.empty()) res_level = surfaces.min_res_level(); else if (!curves.empty()) res_level = curves.min_res_level(); curves.clear(); surfaces.clear(); // XXX - Zachary: add SWEEP_CMD (BOX_CMD?) here: // Create/Edit the top points matching the bottom points // and the curves running vertically between them int i = 0; for ( i=0; i<n; i++ ) { Wvec n = (bot_pts[i]->loc() - o).orthogonalized(t).normalized(); Wvec b = cross(n,t); Wpt_list cpts = spts; cpts.xform( Wtransf(o, t, b, n) ); // XXX - should be undoable if (is_editing) { Wpt_listMap* m = dynamic_cast<Wpt_listMap*>(_curves[i]->map()); cmd->add(make_shared<WPT_LIST_RESHAPE_CMD>(m,cpts)); } else { top_pts += BpointAction::create(_mesh, cpts.back(), b, n, res_level, cmd); curves += BcurveAction::create(_mesh, cpts, b, num_edges , res_level, bot_pts[i], top_pts[i], cmd); } } if (!is_editing) { // Create curves joining each top point to the next. for ( i=0; i<n; i++ ) { int j = (i+1) % n; Bcurve* c = bot_pts[i]->lookup_curve( bot_pts[j] ); if ( !c ) { cerr << "SWEEP_DISK::build_box(): ERROR, can't find boundary curve" << endl; continue; } // Ensure orientation of top and bottom curves is the same. int i1 = i; int i2 = j; if ( c->b1() != bot_pts[i1] ) swap( i1, i2 ); assert( c->b1() == bot_pts[i1] && c->b2() == bot_pts[i2] ); // Create the new top curve with the same shape as the bottom curve. Wpt_list cpts = c->get_wpts(); cpts.fix_endpoints( top_pts[i1]->loc(), top_pts[i2]->loc() ); curves += BcurveAction::create(_mesh, cpts, t, c->num_edges(), res_level, top_pts[i1], top_pts[i2], cmd); build_coons(bot_pts[i], bot_pts[j], top_pts[j], top_pts[i], surfaces, cmd); } // Slap on a top if base is quadrilateral // XXX - should handle other cases if (n == 4) build_coons(top_pts[0], top_pts[1], top_pts[2], top_pts[3], surfaces, cmd); } _mesh->changed(); // set the res level uniformly over the box: for (int i = 0; i < bot_pts.num(); i++) bot_pts[i]->set_res_level(res_level); top_pts.set_res_level(res_level); curves.set_res_level(res_level); surfaces.set_res_level(res_level); _mesh->update_subdivision(res_level); // Record data necessary to return to this mode Panel* p = dynamic_cast<Panel*>(Bsurface::get_surface(_enclosed_faces)); assert(p); if (is_editing) { vector<Panel*>::iterator it = std::find(panels.begin(), panels.end(), p); assert(it != panels.end()); int loc = it - panels.begin(); profiles[loc] = _profile; } else { panels.push_back(p); top_pts += bot_pts; bpoints.push_back(top_pts); bcurves.push_back(curves); bsurfaces.push_back(surfaces); profiles.push_back(_profile); } //FLOOR::realign(_mesh->cur_mesh(), cmd); WORLD::add_command(cmd); return true; }
UVsurface* SWEEP_DISK::build_revolve( CWpt_list& apts, CWvec& n, CWpt_list& spts, MULTI_CMDptr cmd ) { static bool debug = Config::get_var_bool("DEBUG_BUILD_REVOLVE"); // Editing or Creating bool is_editing = !(_surfs.empty()); Bcurve* bcurve = Bcurve::get_curve(_boundary.edges()); if (!bcurve) { err_adv(debug, "SWEEP_DISK::build_revolve: can't find curve"); return nullptr; } if (!bcurve->is_control()) { err_adv(debug, "SWEEP_DISK::build_revolve: error: non-control curve"); return nullptr; } Map1D3D* axis = new Wpt_listMap(apts, new WptMap(apts[0]), new WptMap(apts[1]), n); // XXX - Zachary: add SWEEP_CMD here: // Create/Edit the surface of revolution UVsurface* ret = nullptr; Panel* p = dynamic_cast<Panel*>(Bsurface::get_surface(_enclosed_faces)); assert(p); if (is_editing) { assert(!_surfs.empty()); ret = dynamic_cast<UVsurface*>(_surfs[0]); assert(ret); TubeMap* tmap = dynamic_cast<TubeMap*>(ret->map()); assert(tmap); // reshape the axis Wpt_listMap* m = dynamic_cast<Wpt_listMap*>(tmap->axis()); assert(m); WPT_LIST_RESHAPE_CMDptr a_cmd = make_shared<WPT_LIST_RESHAPE_CMD>(m,apts); if (a_cmd->doit()) cmd->add(a_cmd); // reshape the top curve double s = spts.back()[2]/spts.front()[2]; Wtransf M = tmap->axis()->F(1) * Wtransf::scaling(0,s,s) * tmap->axis()->Finv(0); WPT_LIST_RESHAPE_CMDptr c1_cmd = make_shared<WPT_LIST_RESHAPE_CMD>(((Wpt_listMap*)tmap->c1()), M*((Wpt_listMap*)tmap->c0())->get_wpts()); if (c1_cmd->doit()) cmd->add(c1_cmd); // reshape the profile cmd->add(make_shared<TUBE_MAP_RESHAPE_CMD>(tmap,spts)); // change the record vector<Panel*>::iterator it = std::find(panels.begin(), panels.end(), p); assert(it != panels.end()); int loc = it - panels.begin(); profiles[loc] = _profile; } else { // for recording purposes Bpoint_list points; Bcurve_list curves; Bsurface_list surfs; ret = UVsurface::build_revolve(bcurve, axis, spts, _enclosed_faces, points, curves, surfs, cmd); if (ret) { //FLOOR::realign(ret->cur_mesh(), cmd); panels.push_back(p); bpoints.push_back(points); bcurves.push_back(curves); bsurfaces.push_back(surfs); profiles.push_back(_profile); } } WORLD::add_command(cmd); return ret; }
UVsurface* SWEEP_DISK::build_revolve( CWpt_list& apts, CWvec& n, CWpt_list& spts, MULTI_CMDptr cmd ) { static bool debug = Config::get_var_bool("DEBUG_BUILD_REVOLVE"); // Editing or Creating bool is_editing = !(_surfs.empty()); Bcurve* bcurve = Bcurve::get_curve(_boundary.edges()); if (!bcurve) { err_adv(debug, "SWEEP_DISK::build_revolve: can't find curve"); return 0; } if (!bcurve->is_control()) { err_adv(debug, "SWEEP_DISK::build_revolve: error: non-control curve"); return 0; } Map1D3D* axis = new Wpt_listMap(apts, new WptMap(apts[0]), new WptMap(apts[1]), n); // XXX - Zachary: add SWEEP_CMD here: // Create/Edit the surface of revolution UVsurface* ret = NULL; Panel* p = Panel::upcast(Bsurface::get_surface(_enclosed_faces)); assert(p); if (is_editing) { assert(!_surfs.empty()); ret = UVsurface::upcast(_surfs[0]); assert(ret); TubeMap* tmap = TubeMap::upcast(ret->map()); assert(tmap); // reshape the axis Wpt_listMap* m = Wpt_listMap::upcast(tmap->axis()); assert(m); WPT_LIST_RESHAPE_CMDptr a_cmd = new WPT_LIST_RESHAPE_CMD(m,apts); if (a_cmd->doit()) cmd->add(a_cmd); // reshape the top curve double s = spts.last()[2]/spts.first()[2]; Wtransf M = tmap->axis()->F(1) * Wtransf::scaling(0,s,s) * tmap->axis()->Finv(0); WPT_LIST_RESHAPE_CMDptr c1_cmd = new WPT_LIST_RESHAPE_CMD(((Wpt_listMap*)tmap->c1()), M*((Wpt_listMap*)tmap->c0())->get_wpts()); if (c1_cmd->doit()) cmd->add(c1_cmd); // reshape the profile cmd->add(new TUBE_MAP_RESHAPE_CMD(tmap,spts)); // change the record int loc = panels.get_index(p); assert(loc >= 0); profiles[loc] = _profile; } else { // for recording purposes Bpoint_list points; Bcurve_list curves; Bsurface_list surfs; ret = UVsurface::build_revolve(bcurve, axis, spts, _enclosed_faces, points, curves, surfs, cmd); if (ret) { //FLOOR::realign(ret->cur_mesh(), cmd); panels += p; bpoints += points; bcurves += curves; bsurfaces += surfs; profiles += _profile; } } WORLD::add_command(cmd); return ret; }