Merge branch 'master' into master

This commit is contained in:
sliptonic
2016-06-13 08:25:07 -05:00
committed by GitHub
15 changed files with 3546 additions and 54 deletions

1057
src/Mod/Arch/ArchPrecast.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -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:

View File

@@ -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):

View File

@@ -36,6 +36,7 @@ SET(Arch_SRCS
ArchSchedule.py
ArchProfile.py
import3DS.py
ArchPrecast.py
)
SET(Dice3DS_SRCS

View File

@@ -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>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 25 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 36 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 39 KiB

View File

@@ -43,6 +43,7 @@ typesmap = { "Site": ["IfcSite"],
"Stairs": ["IfcStair", "IfcStairFlight", "IfcRamp", "IfcRampFlight"],
"Space": ["IfcSpace"],
"Rebar": ["IfcReinforcingBar"],
"Panel": ["IfcPlate"],
"Equipment": ["IfcFurnishingElement","IfcSanitaryTerminal","IfcFlowTerminal","IfcElectricAppliance"]
}

View File

@@ -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>

View File

@@ -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, &degMax,
&continuity, &tol3d, &degMin,
&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);

View File

@@ -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):