Merge branch 'master' into master
This commit is contained in:
1057
src/Mod/Arch/ArchPrecast.py
Normal file
1057
src/Mod/Arch/ArchPrecast.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -43,7 +43,7 @@ profilefiles = [os.path.join(FreeCAD.getResourceDir(),"Mod","Arch","Presets","pr
|
||||
os.path.join(os.path.dirname(__file__),"Presets","profiles.csv")]
|
||||
|
||||
def readPresets():
|
||||
Presets=[None]
|
||||
Presets=[]
|
||||
for profilefile in profilefiles:
|
||||
if os.path.exists(profilefile):
|
||||
try:
|
||||
|
||||
@@ -38,18 +38,14 @@ __title__="FreeCAD Structure"
|
||||
__author__ = "Yorik van Havre"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
# Make some strings picked by the translator
|
||||
#if FreeCAD.GuiUp:
|
||||
# QtCore.QT_TRANSLATE_NOOP("Arch","Wood")
|
||||
# QtCore.QT_TRANSLATE_NOOP("Arch","Steel")
|
||||
|
||||
# Possible roles for structural elements
|
||||
Roles = ["Beam","Column","Slab","Wall","Curtain Wall","Roof","Foundation","Pile","Tendon"]
|
||||
|
||||
#Reads preset profiles and categorizes them
|
||||
Categories=[None]
|
||||
Categories=[]
|
||||
Presets=ArchProfile.readPresets()
|
||||
for pre in Presets[1:]:
|
||||
for pre in Presets:
|
||||
if pre[1] not in Categories:
|
||||
Categories.append(pre[1])
|
||||
|
||||
@@ -163,14 +159,17 @@ class _CommandStructure:
|
||||
# interactive mode
|
||||
if hasattr(FreeCAD,"DraftWorkingPlane"):
|
||||
FreeCAD.DraftWorkingPlane.setup()
|
||||
import DraftTrackers
|
||||
import DraftTrackers,ArchPrecast
|
||||
self.points = []
|
||||
self.tracker = DraftTrackers.boxTracker()
|
||||
self.tracker.width(self.Width)
|
||||
self.tracker.height(self.Height)
|
||||
self.tracker.length(self.Length)
|
||||
self.tracker.on()
|
||||
FreeCADGui.Snapper.getPoint(callback=self.getPoint,movecallback=self.update,extradlg=self.taskbox())
|
||||
self.precast = ArchPrecast._PrecastTaskPanel()
|
||||
self.dents = ArchPrecast._DentsTaskPanel()
|
||||
self.precast.Dents = self.dents
|
||||
FreeCADGui.Snapper.getPoint(callback=self.getPoint,movecallback=self.update,extradlg=[self.taskbox(),self.precast.form,self.dents.form])
|
||||
|
||||
def getPoint(self,point=None,obj=None):
|
||||
"this function is called by the snapper when it has a 3D point"
|
||||
@@ -180,19 +179,37 @@ class _CommandStructure:
|
||||
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Structure")))
|
||||
FreeCADGui.addModule("Arch")
|
||||
if self.Profile is not None:
|
||||
FreeCADGui.doCommand('p = Arch.makeProfile('+str(self.Profile)+')')
|
||||
if self.Length == self.Profile[4]:
|
||||
# vertical
|
||||
FreeCADGui.doCommand('s = Arch.makeStructure(p,height='+str(self.Height)+')')
|
||||
if "Precast" in self.Profile:
|
||||
# precast concrete
|
||||
args = self.precast.getValues()
|
||||
args["PrecastType"] = self.Profile.split("_")[1]
|
||||
args["Length"] = self.Length
|
||||
args["Width"] = self.Width
|
||||
args["Height"] = self.Height
|
||||
argstring = ""
|
||||
for pair in args.items():
|
||||
argstring += pair[0].lower() + "="
|
||||
if isinstance(pair[1],str):
|
||||
argstring += '"' + pair[1] + '",'
|
||||
else:
|
||||
argstring += str(pair[1]) + ","
|
||||
FreeCADGui.addModule("ArchPrecast")
|
||||
FreeCADGui.doCommand("s = ArchPrecast.makePrecast("+argstring+")")
|
||||
else:
|
||||
# horizontal
|
||||
FreeCADGui.doCommand('s = Arch.makeStructure(p,height='+str(self.Length)+')')
|
||||
FreeCADGui.doCommand('s.Placement.Rotation = FreeCAD.Rotation(-0.5,0.5,-0.5,0.5)')
|
||||
FreeCADGui.doCommand('s.Profile = "'+self.Profile[2]+'"')
|
||||
# metal profile
|
||||
FreeCADGui.doCommand('p = Arch.makeProfile('+str(self.Profile)+')')
|
||||
if self.Length == self.Profile[4]:
|
||||
# vertical
|
||||
FreeCADGui.doCommand('s = Arch.makeStructure(p,height='+str(self.Height)+')')
|
||||
else:
|
||||
# horizontal
|
||||
FreeCADGui.doCommand('s = Arch.makeStructure(p,height='+str(self.Length)+')')
|
||||
FreeCADGui.doCommand('s.Placement.Rotation = FreeCAD.Rotation(-0.5,0.5,-0.5,0.5)')
|
||||
FreeCADGui.doCommand('s.Profile = "'+self.Profile[2]+'"')
|
||||
else :
|
||||
FreeCADGui.doCommand('s = Arch.makeStructure(length='+str(self.Length)+',width='+str(self.Width)+',height='+str(self.Height)+')')
|
||||
FreeCADGui.doCommand('s.Placement.Base = '+DraftVecUtils.toString(point))
|
||||
FreeCADGui.doCommand('s.Placement.Rotation=FreeCAD.DraftWorkingPlane.getRotation().Rotation')
|
||||
FreeCADGui.doCommand('s.Placement.Rotation=s.Placement.Rotation.multiply(FreeCAD.DraftWorkingPlane.getRotation().Rotation)')
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
if self.continueCmd:
|
||||
@@ -214,15 +231,15 @@ class _CommandStructure:
|
||||
# categories box
|
||||
labelc = QtGui.QLabel(translate("Arch","Category").decode("utf8"))
|
||||
valuec = QtGui.QComboBox()
|
||||
valuec.addItems([" "]+Categories[1:])
|
||||
valuec.addItems([" ","Precast concrete"]+Categories)
|
||||
grid.addWidget(labelc,0,0,1,1)
|
||||
grid.addWidget(valuec,0,1,1,1)
|
||||
|
||||
# presets box
|
||||
labelp = QtGui.QLabel(translate("Arch","Preset").decode("utf8"))
|
||||
self.vPresets = QtGui.QComboBox()
|
||||
self.pSelect=Presets[1:]
|
||||
fpresets = [" "]+self._createItemlist(self.pSelect)
|
||||
self.pSelect = [None]
|
||||
fpresets = [" "]
|
||||
self.vPresets.addItems(fpresets)
|
||||
grid.addWidget(labelp,1,0,1,1)
|
||||
grid.addWidget(self.vPresets,1,1,1,1)
|
||||
@@ -304,31 +321,53 @@ class _CommandStructure:
|
||||
|
||||
def setCategory(self,i):
|
||||
self.vPresets.clear()
|
||||
if i > 0:
|
||||
self.pSelect= [p for p in Presets[1:] if p[1] == Categories[i]]
|
||||
fpresets = [" "]+self._createItemlist(self.pSelect)
|
||||
if i > 1:
|
||||
self.precast.form.hide()
|
||||
self.pSelect = [p for p in Presets if p[1] == Categories[i-2]]
|
||||
fpresets = self._createItemlist(self.pSelect)
|
||||
self.vPresets.addItems(fpresets)
|
||||
self.setPreset(0)
|
||||
elif i == 1:
|
||||
self.precast.form.show()
|
||||
self.pSelect = self.precast.PrecastTypes
|
||||
fpresets = self.precast.PrecastTypes
|
||||
self.vPresets.addItems(fpresets)
|
||||
self.setPreset(0)
|
||||
else:
|
||||
self.pSelect=Presets[1:]
|
||||
fpresets = [" "]+self._createItemlist(self.pSelect)
|
||||
self.precast.form.hide()
|
||||
self.pSelect = [None]
|
||||
fpresets = [" "]
|
||||
self.vPresets.addItems(fpresets)
|
||||
|
||||
def setPreset(self,i):
|
||||
if i > 0:
|
||||
p=self.pSelect[i-1][0]
|
||||
self.vLength.setText(FreeCAD.Units.Quantity(float(Presets[p][4]),FreeCAD.Units.Length).UserString)
|
||||
self.vWidth.setText(FreeCAD.Units.Quantity(float(Presets[p][5]),FreeCAD.Units.Length).UserString)
|
||||
self.Profile = Presets[p]
|
||||
else:
|
||||
self.Profile = None
|
||||
self.Profile = None
|
||||
elt = self.pSelect[i]
|
||||
if elt:
|
||||
if elt in self.precast.PrecastTypes:
|
||||
self.precast.setPreset(elt)
|
||||
self.Profile = "Precast_" + elt
|
||||
if elt == "Pillar":
|
||||
self.dents.form.show()
|
||||
else:
|
||||
self.dents.form.hide()
|
||||
else:
|
||||
p=elt[0]
|
||||
self.vLength.setText(FreeCAD.Units.Quantity(float(Presets[p][4]),FreeCAD.Units.Length).UserString)
|
||||
self.vWidth.setText(FreeCAD.Units.Quantity(float(Presets[p][5]),FreeCAD.Units.Length).UserString)
|
||||
self.Profile = Presets[p]
|
||||
|
||||
|
||||
def rotateLH(self):
|
||||
self.vLength.setText(FreeCAD.Units.Quantity(self.Height,FreeCAD.Units.Length).UserString)
|
||||
self.vHeight.setText(FreeCAD.Units.Quantity(self.Length,FreeCAD.Units.Length).UserString)
|
||||
h = self.Height
|
||||
l = self.Length
|
||||
self.vLength.setText(FreeCAD.Units.Quantity(h,FreeCAD.Units.Length).UserString)
|
||||
self.vHeight.setText(FreeCAD.Units.Quantity(l,FreeCAD.Units.Length).UserString)
|
||||
|
||||
def rotateLW(self):
|
||||
self.vLength.setText(FreeCAD.Units.Quantity(self.Width,FreeCAD.Units.Length).UserString)
|
||||
self.vWidth.setText(FreeCAD.Units.Quantity(self.Length,FreeCAD.Units.Length).UserString)
|
||||
w = self.Width
|
||||
l = self.Length
|
||||
self.vLength.setText(FreeCAD.Units.Quantity(w,FreeCAD.Units.Length).UserString)
|
||||
self.vWidth.setText(FreeCAD.Units.Quantity(l,FreeCAD.Units.Length).UserString)
|
||||
|
||||
|
||||
class _Structure(ArchComponent.Component):
|
||||
|
||||
@@ -36,6 +36,7 @@ SET(Arch_SRCS
|
||||
ArchSchedule.py
|
||||
ArchProfile.py
|
||||
import3DS.py
|
||||
ArchPrecast.py
|
||||
)
|
||||
|
||||
SET(Dice3DS_SRCS
|
||||
|
||||
@@ -70,6 +70,12 @@
|
||||
<file>ui/ParametersWindowStash.svg</file>
|
||||
<file>ui/ParametersDoorSimple.svg</file>
|
||||
<file>ui/ParametersDoorGlass.svg</file>
|
||||
<file>ui/ParametersBeam.svg</file>
|
||||
<file>ui/ParametersPillar.svg</file>
|
||||
<file>ui/ParametersDent.svg</file>
|
||||
<file>ui/ParametersPanel.svg</file>
|
||||
<file>ui/ParametersSlab.svg</file>
|
||||
<file>ui/ParametersIbeam.svg</file>
|
||||
<file>translations/Arch_af.qm</file>
|
||||
<file>translations/Arch_de.qm</file>
|
||||
<file>translations/Arch_fi.qm</file>
|
||||
|
||||
346
src/Mod/Arch/Resources/ui/ParametersBeam.svg
Normal file
346
src/Mod/Arch/Resources/ui/ParametersBeam.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 25 KiB |
394
src/Mod/Arch/Resources/ui/ParametersDent.svg
Normal file
394
src/Mod/Arch/Resources/ui/ParametersDent.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 30 KiB |
289
src/Mod/Arch/Resources/ui/ParametersIbeam.svg
Normal file
289
src/Mod/Arch/Resources/ui/ParametersIbeam.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 23 KiB |
350
src/Mod/Arch/Resources/ui/ParametersPanel.svg
Normal file
350
src/Mod/Arch/Resources/ui/ParametersPanel.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 28 KiB |
452
src/Mod/Arch/Resources/ui/ParametersPillar.svg
Normal file
452
src/Mod/Arch/Resources/ui/ParametersPillar.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 36 KiB |
444
src/Mod/Arch/Resources/ui/ParametersSlab.svg
Normal file
444
src/Mod/Arch/Resources/ui/ParametersSlab.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 39 KiB |
@@ -43,6 +43,7 @@ typesmap = { "Site": ["IfcSite"],
|
||||
"Stairs": ["IfcStair", "IfcStairFlight", "IfcRamp", "IfcRampFlight"],
|
||||
"Space": ["IfcSpace"],
|
||||
"Rebar": ["IfcReinforcingBar"],
|
||||
"Panel": ["IfcPlate"],
|
||||
"Equipment": ["IfcFurnishingElement","IfcSanitaryTerminal","IfcFlowTerminal","IfcElectricAppliance"]
|
||||
}
|
||||
|
||||
|
||||
@@ -293,12 +293,37 @@ from the knots table of this B-Spline curve.</UserDocu>
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="approximate">
|
||||
<Methode Name="approximate" Keyword="true">
|
||||
<Documentation>
|
||||
<UserDocu>
|
||||
approximate(list_of_points):
|
||||
|
||||
Replaces this B-Spline curve by approximating a set of points.
|
||||
The function accepts keywords as arguments.
|
||||
|
||||
approximate2(Points = list_of_points)
|
||||
|
||||
Optional arguments :
|
||||
|
||||
DegMin = integer (3) : Minimum degree of the curve.
|
||||
DegMax = integer (8) : Maximum degree of the curve.
|
||||
Tolerance = float (1e-3) : approximating tolerance.
|
||||
Continuity = string ('C2') : Desired continuity of the curve.
|
||||
Possible values : 'C0','G1','C1','G2','C2','C3','CN'
|
||||
|
||||
LengthWeight = float, CurvatureWeight = float, TorsionWeight = float
|
||||
If one of these arguments is not null, the functions approximates the
|
||||
points using variational smoothing algorithm, which tries to minimize
|
||||
additional criterium:
|
||||
LengthWeight*CurveLength + CurvatureWeight*Curvature + TorsionWeight*Torsion
|
||||
Continuity must be C0, C1 or C2, else defaults to C2.
|
||||
|
||||
Parameters = list of floats : knot sequence of the approximated points.
|
||||
This argument is only used if the weights above are all null.
|
||||
|
||||
ParamType = string ('Uniform','Centripetal' or 'ChordLength')
|
||||
Parameterization type. Only used if weights and Parameters above aren't specified.
|
||||
|
||||
Note : Continuity of the spline defaults to C2. However, it may not be applied if
|
||||
it conflicts with other parameters ( especially DegMax ).
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
# include <GeomAPI_PointsToBSpline.hxx>
|
||||
# include <GeomAPI_Interpolate.hxx>
|
||||
# include <GeomConvert_BSplineCurveToBezierCurve.hxx>
|
||||
# include <Standard_PrimitiveTypes.hxx>
|
||||
# include <gp_Pnt.hxx>
|
||||
# include <TColStd_Array1OfReal.hxx>
|
||||
# include <TColgp_Array1OfPnt.hxx>
|
||||
@@ -34,8 +35,9 @@
|
||||
# include <TColgp_HArray1OfPnt.hxx>
|
||||
# include <TColStd_Array1OfInteger.hxx>
|
||||
# include <TColStd_HArray1OfReal.hxx>
|
||||
# include <TColStd_Array1OfReal.hxx>
|
||||
# include <TColStd_HArray1OfBoolean.hxx>
|
||||
# include <TColgp_HArray1OfPnt.hxx>
|
||||
|
||||
# include <Precision.hxx>
|
||||
#endif
|
||||
|
||||
@@ -743,11 +745,29 @@ PyObject* BSplineCurvePy::toBiArcs(PyObject * args)
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* BSplineCurvePy::approximate(PyObject *args)
|
||||
PyObject* BSplineCurvePy::approximate(PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject* obj;
|
||||
if (!PyArg_ParseTuple(args, "O", &obj))
|
||||
Standard_Integer degMin=3;
|
||||
Standard_Integer degMax=8;
|
||||
char* continuity = "C2";
|
||||
double tol3d = 1e-3;
|
||||
char* parType = "ChordLength";
|
||||
PyObject* par = 0;
|
||||
double weight1 = 0;
|
||||
double weight2 = 0;
|
||||
double weight3 = 0;
|
||||
|
||||
static char* kwds_interp[] = {"Points", "DegMax", "Continuity", "Tolerance", "DegMin", "ParamType", "Parameters",
|
||||
"LengthWeight", "CurvatureWeight", "TorsionWeight", NULL};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|isdisOddd",kwds_interp,
|
||||
&obj, °Max,
|
||||
&continuity, &tol3d, °Min,
|
||||
&parType, &par,
|
||||
&weight1, &weight2, &weight3))
|
||||
return 0;
|
||||
|
||||
try {
|
||||
Py::Sequence list(obj);
|
||||
TColgp_Array1OfPnt pnts(1,list.size());
|
||||
@@ -757,7 +777,77 @@ PyObject* BSplineCurvePy::approximate(PyObject *args)
|
||||
pnts(index++) = gp_Pnt(vec.x,vec.y,vec.z);
|
||||
}
|
||||
|
||||
GeomAPI_PointsToBSpline fit(pnts);
|
||||
if (degMin > degMax) {
|
||||
Standard_Failure::Raise("DegMin must be lower or equal to DegMax");
|
||||
}
|
||||
|
||||
GeomAbs_Shape c;
|
||||
std::string str = continuity;
|
||||
if (str == "C0")
|
||||
c = GeomAbs_C0;
|
||||
else if (str == "G1")
|
||||
c = GeomAbs_G1;
|
||||
else if (str == "C1")
|
||||
c = GeomAbs_C1;
|
||||
else if (str == "G2")
|
||||
c = GeomAbs_G2;
|
||||
else if (str == "C2")
|
||||
c = GeomAbs_C2;
|
||||
else if (str == "C3")
|
||||
c = GeomAbs_C3;
|
||||
else if (str == "CN")
|
||||
c = GeomAbs_CN;
|
||||
else
|
||||
c = GeomAbs_C2;
|
||||
|
||||
if (weight1 || weight2 || weight3) {
|
||||
// It seems that this function only works with Continuity = C0, C1 or C2
|
||||
if (!(c == GeomAbs_C0 || c == GeomAbs_C1 || c == GeomAbs_C2)) {
|
||||
c = GeomAbs_C2;
|
||||
}
|
||||
GeomAPI_PointsToBSpline fit(pnts, weight1, weight2, weight3, degMax, c, tol3d);
|
||||
Handle_Geom_BSplineCurve spline = fit.Curve();
|
||||
if (!spline.IsNull()) {
|
||||
this->getGeomBSplineCurvePtr()->setHandle(spline);
|
||||
Py_Return;
|
||||
}
|
||||
else {
|
||||
Standard_Failure::Raise("Smoothing approximation failed");
|
||||
return 0; // goes to the catch block
|
||||
}
|
||||
}
|
||||
|
||||
if (par) {
|
||||
Py::Sequence plist(par);
|
||||
TColStd_Array1OfReal parameters(1,plist.size());
|
||||
Standard_Integer index = 1;
|
||||
for (Py::Sequence::iterator it = plist.begin(); it != plist.end(); ++it) {
|
||||
Py::Float f(*it);
|
||||
parameters(index++) = static_cast<double>(f);
|
||||
}
|
||||
|
||||
GeomAPI_PointsToBSpline fit(pnts, parameters, degMin, degMax, c, tol3d);
|
||||
Handle_Geom_BSplineCurve spline = fit.Curve();
|
||||
if (!spline.IsNull()) {
|
||||
this->getGeomBSplineCurvePtr()->setHandle(spline);
|
||||
Py_Return;
|
||||
}
|
||||
else {
|
||||
Standard_Failure::Raise("Approximation with parameters failed");
|
||||
return 0; // goes to the catch block
|
||||
}
|
||||
}
|
||||
|
||||
Approx_ParametrizationType pt;
|
||||
std::string pstr = parType;
|
||||
if (pstr == "Uniform")
|
||||
pt = Approx_IsoParametric;
|
||||
else if (pstr == "Centripetal")
|
||||
pt = Approx_Centripetal;
|
||||
else
|
||||
pt = Approx_ChordLength;
|
||||
|
||||
GeomAPI_PointsToBSpline fit(pnts, pt, degMin, degMax, c, tol3d);
|
||||
Handle_Geom_BSplineCurve spline = fit.Curve();
|
||||
if (!spline.IsNull()) {
|
||||
this->getGeomBSplineCurvePtr()->setHandle(spline);
|
||||
|
||||
@@ -33,6 +33,14 @@ if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui
|
||||
from DraftTools import translate
|
||||
# Qt tanslation handling
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def translate(context, text, disambig=None):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def translate(context, text, disambig=None):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
else:
|
||||
def translate(ctxt, txt):
|
||||
return txt
|
||||
@@ -43,16 +51,6 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
"""Path Profile object and FreeCAD command"""
|
||||
|
||||
# Qt tanslation handling
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def translate(context, text, disambig=None):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def translate(context, text, disambig=None):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
|
||||
class ObjectProfile:
|
||||
|
||||
def __init__(self, obj):
|
||||
|
||||
Reference in New Issue
Block a user