Files
create/src/Mod/Surface/App/FeatureBezSurf.cpp
balazs-bamer 00f245efdd Transformed Bezier curves work now
One gets the curve and the location from the healed wire. However, the
curve has the original coordinates, the transformation the user used to
obtain it need to be applied before adding it to the surface builder.
2017-04-17 16:20:44 +02:00

243 lines
8.3 KiB
C++

/***************************************************************************
* Copyright (c) 2014 Nathan Miller <Nathan.A.Mill[at]gmail.com> *
* Balázs Bámer *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <BRepBuilderAPI_MakeFace.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Wire.hxx>
#include <Geom_BezierCurve.hxx>
#include <Precision.hxx>
#include <gp_Trsf.hxx>
#endif
#include "FeatureBezSurf.h"
#include "FillType.h"
#include <GeomFill.hxx>
#include <GeomFill_BezierCurves.hxx>
#include <ShapeFix_Wire.hxx>
#include <ShapeExtend_WireData.hxx>
#include <BRep_Tool.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <Base/Tools.h>
#include <Base/Exception.h>
#include <TopExp_Explorer.hxx>
using namespace Surface;
PROPERTY_SOURCE(Surface::BezSurf, Part::Feature)
//Initial values
BezSurf::BezSurf()
{
ADD_PROPERTY(aBezList,(0,"Geom_BezierCurve"));
ADD_PROPERTY(filltype,(1));
}
//Structures
struct crvs{
Handle_Geom_BezierCurve C1;
Handle_Geom_BezierCurve C2;
Handle_Geom_BezierCurve C3;
Handle_Geom_BezierCurve C4;
};
//Functions
void getCurves(GeomFill_BezierCurves& aBuilder,TopoDS_Wire& aWire, const App::PropertyLinkSubList& anEdge, GeomFill_FillingStyle fstyle);
//bool orderCurves(crvs& Cs, int size);
//Check if any components of the surface have been modified
short BezSurf::mustExecute() const
{
if (aBezList.isTouched() ||
filltype.isTouched())
return 1;
return 0;
}
App::DocumentObjectExecReturn *BezSurf::execute(void)
{
//Set Variables
int ftype = filltype.getValue();
//Begin Construction
try{
//Identify filling style
GeomFill_FillingStyle fstyle;
if(ftype==StretchStyle) {fstyle = GeomFill_StretchStyle;}
else if(ftype==CoonsStyle) {fstyle = GeomFill_CoonsStyle;}
else if(ftype==CurvedStyle) {fstyle = GeomFill_CurvedStyle;}
else {return new App::DocumentObjectExecReturn("Filling style must be 1 (Stretch), 2 (Coons), or 3 (Curved).");}
//Create Bezier Surface
GeomFill_BezierCurves aSurfBuilder; //Create Surface Builder
// BRepBuilderAPI_MakeWire aWireBuilder; //Create Wire Builder
TopoDS_Wire aWire; //Create empty wire
//Get Bezier Curves from edges and initialize the builder
getCurves(aSurfBuilder,aWire,aBezList,fstyle);
//Create the surface
const Handle_Geom_BezierSurface aSurface = aSurfBuilder.Surface();
BRepBuilderAPI_MakeFace aFaceBuilder;//(aSurface,aWire,Standard_True); //Create Face Builder
Standard_Real u0 = 0.;
Standard_Real u1 = 1.;
Standard_Real v0 = 0.;
Standard_Real v1 = 1.;
aFaceBuilder.Init(aSurface,u0,u1,v0,v1,Precision::Confusion());
TopoDS_Face aFace = aFaceBuilder.Face(); //Returned Face
if(!aFaceBuilder.IsDone()){return new App::DocumentObjectExecReturn("Face unable to be constructed");}
if (aFace.IsNull()){
return new App::DocumentObjectExecReturn("Resulting Face is null");
}
this->Shape.setValue(aFace);
return App::DocumentObject::StdReturn;
} //End Try
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();
return new App::DocumentObjectExecReturn(e->GetMessageString());
} //End Catch
} //End execute
void getCurves(GeomFill_BezierCurves& aBuilder,TopoDS_Wire& aWire, const App::PropertyLinkSubList& anEdge, GeomFill_FillingStyle fstyle){
//void getCurves(TopoDS_Wire& aWire, const App::PropertyLinkSubList& anEdge){
crvs bcrv;
Standard_Real u0;// contains output
Standard_Real u1;// contains output
Handle(ShapeFix_Wire) aShFW = new ShapeFix_Wire;
Handle(ShapeExtend_WireData) aWD = new ShapeExtend_WireData;
if(anEdge.getSize()>4){Standard_Failure::Raise("Only 2-4 continuous Bezier Curves are allowed");return;}
if(anEdge.getSize()<2){Standard_Failure::Raise("Only 2-4 continuous Bezier Curves are allowed");return;}
for(int i=0; i<anEdge.getSize(); i++){
Part::TopoShape ts; //Curve TopoShape
TopoDS_Shape sub; //Curve TopoDS_Shape
TopoDS_Edge etmp; //Curve TopoDS_Edge
//Get Edge
App::PropertyLinkSubList::SubSet set = anEdge[i];
if(set.obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
ts = static_cast<Part::Feature*>(set.obj)->Shape.getShape();
//we want only the subshape which is linked
sub = ts.getSubShape(set.sub);
if(sub.ShapeType() == TopAbs_EDGE) { //Check Shape type and assign edge
etmp = TopoDS::Edge(sub);
}
else {
Standard_Failure::Raise("Curves must be type TopoDS_Edge");
return; //Raise exception
}
aWD->Add(etmp);
}
else{Standard_Failure::Raise("Curve not from Part::Feature");return;}
}
//Reorder the curves and fix the wire if required
aShFW->Load(aWD); //Load in the wire
aShFW->FixReorder(); //Fix the order of the edges if required
aShFW->ClosedWireMode() = Standard_True; //Enables closed wire mode
aShFW->FixConnected(); //Fix connection between wires
aShFW->FixSelfIntersection(); //Fix Self Intersection
aShFW->Perform(); //Perform the fixes
aWire = aShFW->Wire(); //Healed Wire
if(aWire.IsNull()){Standard_Failure::Raise("Wire unable to be constructed");return;}
//Create Bezier Surface
TopExp_Explorer anExp (aWire, TopAbs_EDGE);
int it = 0;
for (; anExp.More(); anExp.Next()) {
printf("it: %i",it);
const TopoDS_Edge hedge = TopoDS::Edge (anExp.Current());
TopLoc_Location heloc; // this will be output
Handle_Geom_Curve c_geom = BRep_Tool::Curve(hedge,heloc,u0,u1); //The geometric curve
Handle_Geom_BezierCurve b_geom = Handle_Geom_BezierCurve::DownCast(c_geom); //Try to get Bezier curve
if (!b_geom.IsNull()) {
gp_Trsf transf = heloc.Transformation();
b_geom->Transform(transf); // apply original transformation to control points
//Store Underlying Geometry
if(it==0){bcrv.C1 = b_geom;}
else if(it==1){bcrv.C2 = b_geom;}
else if(it==2){bcrv.C3 = b_geom;}
else if(it==3){bcrv.C4 = b_geom;}
}
else {
Standard_Failure::Raise("Curve not a Bezier Curve");
return;
}
it++;
}
int ncrv = anEdge.getSize();
if(ncrv==2){aBuilder.Init(bcrv.C1,bcrv.C2,fstyle);}
else if(ncrv==3){aBuilder.Init(bcrv.C1,bcrv.C2,bcrv.C3,fstyle);}
else if(ncrv==4){aBuilder.Init(bcrv.C1,bcrv.C2,bcrv.C3,bcrv.C4,fstyle);}
return;
}