Example #1
0
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