Path.Area: fixed non-circular curve handling, etc.

* Fixed non-circular curve orientation handling

* Section changed to use Part::CrossSection, because it seems
BRepAlgoAPI_Section has trouble with non-circular curves (LastParameter
becomes huge which causes discretization to produce many many points)

* Exposed Area.makeSections() to section with variable heights

* Modified Area.setPlane() to accept non-planar shape

* Exposed Area.getPlane() to obtain current workplane

* Exposed Area.Shapes attribute to return the current holding children
shape.
This commit is contained in:
Zheng, Lei
2017-01-29 18:24:01 +08:00
parent 41c7827287
commit 228a0dc905
6 changed files with 564 additions and 229 deletions

View File

@@ -54,11 +54,11 @@ static const AreaDoc myDocs[] = {
"add((shape...)," PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_OPCODE) "):\n"
"Add TopoShape(s) with given operation code\n"
PARAM_PY_DOC(ARG,AREA_PARAMS_OPCODE)
"\nThe first shape's wires will be fused together regardless of the op code given.\n"
"Subsequent shape's wire will be combined using the op code. All shape wires\n"
"shall be coplanar, and are used to determine a working plane for face making and\n"
"offseting. You can call setPlane() to supply a reference shape to determin the\n"
"working plane in case the added shapes are all colinear lines.\n",
"\nThe first shape's wires will be unioned together regardless of the op code given\n"
"(except for 'Compound'). Subsequent shape's wire will be combined using the op code.\n"
"All shape wires shall be coplanar, and are used to determine a working plane for face\n"
"making and offseting. You can call setPlane() to supply a reference shape to determin\n"
"the workplane in case the added shapes are all colinear lines.\n",
},
{
@@ -77,6 +77,17 @@ static const AreaDoc myDocs[] = {
"\n* index (-1): the index of the section. -1 means all sections. No effect on planar shape.\n"
PARAM_PY_DOC(ARG,AREA_PARAMS_POCKET),
},
{
"makeSections",
"makeSections(" PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_SECTION_EXTRA) ", heights=[], plane=None):\n"
"Make a list of area holding the sectioned children shapes on given heights\n"
PARAM_PY_DOC(ARG,AREA_PARAMS_SECTION_EXTRA)
"\n* heights ([]): a list of section heights, the meaning of the value is determined by 'mode'.\n"
"If not specified, the current SectionCount, and SectionOffset of this Area is used.\n"
"\n* plane (None): optional shape to specify a section plane. If not give, the current workplane\n"
"of this Area is used.",
},
{
"sortWires",
@@ -270,6 +281,53 @@ PyObject* AreaPy::makePocket(PyObject *args, PyObject *keywds)
return Py::new_reference_to(Part::shape2pyshape(resultShape));
}
PyObject* AreaPy::makeSections(PyObject *args, PyObject *keywds)
{
static char *kwlist[] = {PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_SECTION_EXTRA),
"heights", "plane", NULL};
PyObject *heights = NULL;
PyObject *plane = NULL;
PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_SECTION_EXTRA)
if (!PyArg_ParseTupleAndKeywords(args, keywds,
"|" PARAM_PY_KWDS(AREA_PARAMS_SECTION_EXTRA) "OO!", kwlist,
PARAM_REF(PARAM_FARG,AREA_PARAMS_SECTION_EXTRA),
&heights, &(Part::TopoShapePy::Type), &plane))
return 0;
std::vector<double> h;
if(heights) {
if (PyObject_TypeCheck(heights, &(PyFloat_Type)))
h.push_back(PyFloat_AsDouble(heights));
else if (PyObject_TypeCheck(heights, &(PyList_Type)) ||
PyObject_TypeCheck(heights, &(PyTuple_Type))) {
Py::Sequence shapeSeq(heights);
h.reserve(shapeSeq.size());
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) {
PyObject* item = (*it).ptr();
if(!PyObject_TypeCheck(item, &(PyFloat_Type))) {
PyErr_SetString(PyExc_TypeError, "heights must only contain float type");
return 0;
}
h.push_back(PyFloat_AsDouble(item));
}
}else{
PyErr_SetString(PyExc_TypeError, "heights must be of type float or list/tuple of float");
return 0;
}
}
std::vector<std::shared_ptr<Area> > sections = getAreaPtr()->makeSections(
PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_SECTION_EXTRA),
h,plane?GET_TOPOSHAPE(plane):TopoDS_Shape());
Py::List ret;
for(auto &area : sections)
ret.append(Py::asObject(new AreaPy(new Area(*area,false))));
return Py::new_reference_to(ret);
}
PyObject* AreaPy::setParams(PyObject *args, PyObject *keywds)
{
static char *kwlist[] = {PARAM_FIELD_STRINGS(NAME,AREA_PARAMS_CONF),NULL};
@@ -337,6 +395,20 @@ Py::List AreaPy::getSections(void) const {
return ret;
}
Py::List AreaPy::getShapes(void) const {
Py::List ret;
Area *area = getAreaPtr();
const std::list<Area::Shape> &shapes = area->getChildren();
for(auto &s : shapes)
ret.append(Py::TupleN(Part::shape2pyshape(s.shape),Py::Int(s.op)));
return ret;
}
Py::Object AreaPy::getWorkplane(void) const {
return Part::shape2pyshape(getAreaPtr()->getPlane());
}
// custom attributes get/set
PyObject *AreaPy::getCustomAttributes(const char* /*attr*/) const