/** The location is relative both to (0,0,0) and, from there, to the point along the text string for this character. The transformation matrix is both a translation (movement) and a rotation function that is maintained by the HText class based on where the operator has placed the text. i.e. the location is in 'internal' coordinates and those are then transformed (moved and/or rotated) by the rotation matrix to determine the final coordinates. This is handled differently to the glCommands() method because the OpenGL libraries will have had the transformation matrix pushed onto the stack so that all OpenGL coordinates will be implicitly transformed. */ HeeksObj *VectorFont::Glyph::Sketch( const gp_Pnt & location, const gp_Trsf & transformation_matrix, const float width, COrientationModifier *pOrientationModifier ) const { HeeksObj *sketch = heekscad_interface.NewSketch(); for (GraphicsList_t::const_iterator l_itGraphic = m_graphics_list.begin(); l_itGraphic != m_graphics_list.end(); l_itGraphic++) { sketch->Add((*l_itGraphic)->Sketch( location, transformation_matrix, width, pOrientationModifier ), NULL); } // End for return(sketch); } // End Sketch() method
static void SimplifySketch(const double deviation, bool make_bspline ) { wxGetApp().CreateUndoPoint(); double original_tolerance = wxGetApp().m_geom_tol; wxGetApp().m_geom_tol = sketch_tool_options.m_cleanup_tolerance; std::list<HeeksObj *> selected_sketches; std::copy( wxGetApp().m_marked_list->list().begin(), wxGetApp().m_marked_list->list().end(), std::inserter( selected_sketches, selected_sketches.begin() )); std::list<HeeksObj*>::const_iterator It; for(It = selected_sketches.begin(); It != selected_sketches.end(); It++){ HeeksObj* object = *It; std::list<HeeksObj *> new_objects; if (object->GetType() == SketchType) { std::list<TopoDS_Shape> wires; try { heekscad_interface.ConvertSketchToFaceOrWire(object, wires, false); } // End try catch(...) { continue; } for (std::list<TopoDS_Shape>::iterator itWire = wires.begin(); itWire != wires.end(); itWire++) { std::list<SimplifySketchTool::SortPoint> points = SimplifySketchTool::GetPoints( TopoDS::Wire(*itWire), deviation ); if (sketch_tool_options.m_sort_points) { // The sort points option is turned on. The idea of this is to detect shapes that include // sections that 'double back' on themselves. The first example being a shape made up of // a box as well as a single line that layed along one edge of the box. In this case the extra // line was superfluous. If we sort the points so that each point is closest to the previous // point then, hopefully, we will reorder these shapes that double back on themselves. If this // doesn't work then the user can always turn the 'sort points' option off and try again. std::vector<SimplifySketchTool::SortPoint> sorted_points; std::copy( points.begin(), points.end(), std::inserter( sorted_points, sorted_points.begin() )); for (std::vector<SimplifySketchTool::SortPoint>::iterator l_itPoint = sorted_points.begin(); l_itPoint != sorted_points.end(); l_itPoint++) { // We've already begun. Just sort based on the previous point's location. std::vector<SimplifySketchTool::SortPoint>::iterator l_itNextPoint = l_itPoint; l_itNextPoint++; if (l_itNextPoint != sorted_points.end()) { SimplifySketchTool::sort_points_by_distance compare( *l_itPoint ); std::sort( l_itNextPoint, sorted_points.end(), compare ); } // End if - then } // End for points.clear(); std::copy( sorted_points.begin(), sorted_points.end(), std::inserter( points, points.begin() )); // This sorting process will have resulted in the start and end points being located next to each other // and hence removed. If the original wire was periodic (closed shape) then make sure the last point // is the same as the first point. TopoDS_Wire wire(TopoDS::Wire(*itWire)); if (wire.Closed()) { if (*(points.begin()) != *(points.rbegin())) { points.push_back(*points.begin()); // Close the shape manually. } } } // Whether we sorted or not, we may want to close the shape. if (sketch_tool_options.m_force_closed_shape) { if (*(points.begin()) != *(points.rbegin())) { points.push_back(*points.begin()); // Close the shape manually. } } // Now keep removing points from this list as long as the midpoints are within deviation of // the line between the two neighbour points. bool points_removed = false; do { points_removed = false; for (std::list<SimplifySketchTool::SortPoint>::iterator itPoint = points.begin(); itPoint != points.end(); itPoint++ ) { std::list<SimplifySketchTool::SortPoint>::iterator itP1 = itPoint; std::list<SimplifySketchTool::SortPoint>::iterator itP2 = itPoint; std::list<SimplifySketchTool::SortPoint>::iterator itP3 = itPoint; itP2++; if (itP2 != points.end()) { itP3 = itP2; itP3++; if (itP3 != points.end()) { // First see if p1 and p2 are too close to each other. if (itP1->Distance(*itP2) < deviation) { // Discard p2. points.erase(itP2); points_removed = true; continue; } if (itP2->Distance(*itP3) < deviation) { // Discard p2 points.erase(itP2); points_removed = true; continue; } if (itP1->Distance(*itP3) > deviation) { // Now draw a line between p1 and p3. Measure the distance between p2 and the nearest point // along that line. If this distance is less than the max deviation then discard p2. gp_Lin line(*itP1, gp_Dir(itP3->X() - itP1->X(), itP3->Y() - itP1->Y(), itP3->Z() - itP1->Z())); if (line.SquareDistance(*itP2) < deviation) { // Discard p2 points.erase(itP2); points_removed = true; continue; } } } } } // End for } while (points_removed == true); if (points.size() >= 2) { if (make_bspline) { try { TColgp_Array1OfPnt Points(0, points.size()-1); Standard_Integer i=0; for (std::list<SimplifySketchTool::SortPoint>::iterator itPoint = points.begin(); itPoint != points.end(); itPoint++, i++) { Points.SetValue(i, *itPoint); } // GeomAPI_PointsToBSpline bspline(Points); GeomAPI_PointsToBSpline bspline(Points, sketch_tool_options.m_degree_min, sketch_tool_options.m_degree_max, GeomAbs_Shape(sketch_tool_options.m_continuity), sketch_tool_options.m_cleanup_tolerance); // Standard_EXPORT GeomAPI_PointsToBSpline(const TColgp_Array1OfPnt& Points,const Standard_Integer DegMin = 3,const Standard_Integer DegMax = 8,const GeomAbs_Shape Continuity = GeomAbs_C2,const Standard_Real Tol3D = 1.0e-3); HSpline *hspline = new HSpline(bspline.Curve(), &(wxGetApp().current_color)); heekscad_interface.Add( hspline, NULL ); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); wxMessageBox(_("Failed to create BSpline curve")); } } // End if - then else { // We're making straight lines HeeksObj *sketch = heekscad_interface.NewSketch(); for (std::list<SimplifySketchTool::SortPoint>::iterator itPoint = points.begin(); itPoint != points.end(); itPoint++) { std::list<SimplifySketchTool::SortPoint>::iterator itNext = itPoint; itNext++; if (itNext == points.end()) continue; double start[3], end[3]; itPoint->ToDoubleArray(start); itNext->ToDoubleArray(end); sketch->Add(heekscad_interface.NewLine(start, end), NULL); } // End for // heekscad_interface.Add(sketch, NULL); new_objects.push_back(sketch); } // End if - else } // End if - then } // End for if (new_objects.size() > 0) { #ifdef MULTIPLE_OWNERS std::list<HeeksObj *> parents = object->Owners(); for (std::list<HeeksObj *>::iterator itOwner = parents.begin(); itOwner != parents.end(); itOwner++) { #else if(object->m_owner) { #endif if ((object->CanEditString()) && (object->GetShortString())) { // (*itOwner)->Remove(object); // Mark the old sketches with a name that can be easily recognised so that we can delete the // old objects if we're satisfied with the replacements. wxString title; title << _("Replaced ") << object->GetShortString(); object->OnEditString(title); } // End if - then for (std::list<HeeksObj *>::iterator itNewChild = new_objects.begin(); itNewChild != new_objects.end(); itNewChild++) { #ifdef MULTIPLE_OWNERS (*itOwner)->Add( *itNewChild, NULL ); #else object->m_owner->Add( *itNewChild, NULL ); #endif } // End for } // End for } // End if - then } // End if - then } // End for wxGetApp().m_geom_tol = original_tolerance; wxGetApp().Changed(); } void SimplifySketchTool::Run() { SimplifySketch(m_deviation, false); } // End Run() method