Base::Vector3d TransformStrategy::getRotationCenter() const { // get the global bounding box of all selected objects and use its center as // rotation center std::set<App::DocumentObject*> objects = transformObjects(); if (!objects.empty()) { Base::BoundBox3d bbox; bool first=true; for (std::set<App::DocumentObject*>::const_iterator it=objects.begin();it!=objects.end();++it) { std::map<std::string,App::Property*> props; (*it)->getPropertyMap(props); // search for a data property std::map<std::string,App::Property*>::iterator jt; jt = std::find_if(props.begin(), props.end(), find_geometry_data()); if (jt != props.end()) { if (first) bbox = (static_cast<App::PropertyGeometry*>(jt->second)->getBoundingBox()); else bbox.Add(static_cast<App::PropertyGeometry*>(jt->second)->getBoundingBox()); first = false; } } return Base::Vector3d((bbox.MinX+bbox.MaxX)/2, (bbox.MinY+bbox.MaxY)/2, (bbox.MinZ+bbox.MaxZ)/2); } return Base::Vector3d(); }
Base::BoundBox3d PropertyPointKernel::getBoundingBox() const { Base::BoundBox3d box; for (PointKernel::const_iterator it = _cPoints->begin(); it != _cPoints->end(); ++it) box.Add(*it); return box; }
Base::BoundBox3d DrawProjGroup::getBoundingBox() const { Base::BoundBox3d bbox; std::vector<App::DocumentObject*> views = Views.getValues(); TechDraw::DrawProjGroupItem *anchorView = dynamic_cast<TechDraw::DrawProjGroupItem *>(Anchor.getValue()); for (std::vector<App::DocumentObject*>::const_iterator it = views.begin(); it != views.end(); ++it) { if ((*it)->getTypeId().isDerivedFrom(DrawViewPart::getClassTypeId())) { DrawViewPart *part = static_cast<DrawViewPart *>(*it); Base::BoundBox3d bb = part->getBoundingBox(); bb.ScaleX(1. / part->Scale.getValue()); bb.ScaleY(1. / part->Scale.getValue()); // X and Y of dependant views are relative to the anchorView if (part != anchorView) { bb.MoveX(part->X.getValue()); bb.MoveY(part->Y.getValue()); } bbox.Add(bb); } } // This /should/ leave the centre of the bounding box at (0,0) except when // we're in the process of updating the anchor view's position (eg called // by moveToCentre()) if (anchorView) { //TODO: It looks like we might be getting called before an anchor view is set - weird... bbox.MoveX(anchorView->X.getValue()); bbox.MoveY(anchorView->Y.getValue()); } return bbox; }
Base::BoundBox3d PointKernel::getBoundBox(void)const { Base::BoundBox3d bnd; for (const_point_iterator it = begin(); it != end(); ++it) bnd.Add(*it); return bnd; }
void onSelectionChanged(const Gui::SelectionChanges& msg) { Base::BoundBox3d bbox; unsigned long countPoints=0, countFacets=0; std::vector<Mesh::Feature*> mesh = Gui::Selection().getObjectsOfType<Mesh::Feature>(); for (std::vector<Mesh::Feature*>::iterator it = mesh.begin(); it != mesh.end(); ++it) { countPoints += (*it)->Mesh.getValue().countPoints(); countFacets += (*it)->Mesh.getValue().countFacets(); bbox.Add((*it)->Mesh.getBoundingBox()); } if (countPoints > 0) { numPoints->setText(QString::number(countPoints)); numFacets->setText(QString::number(countFacets)); numMin->setText(QString::fromAscii("X: %1\tY: %2\tZ: %3") .arg(bbox.MinX).arg(bbox.MinX).arg(bbox.MinX)); numMax->setText(QString::fromAscii("X: %1\tY: %2\tZ: %3") .arg(bbox.MaxX).arg(bbox.MaxX).arg(bbox.MaxX)); } else { numPoints->setText(QString::fromAscii("")); numFacets->setText(QString::fromAscii("")); numMin->setText(QString::fromAscii("")); numMax->setText(QString::fromAscii("")); } }
Base::BoundBox3d GeometryObject::boundingBoxOfAoe(const Ellipse *aoe, double start, double end, bool cw) const { // Using the ellipse form: // (xc, yc) = centre of ellipse // phi = angle of ellipse major axis off X axis // a, b = half of major, minor axes // // x(theta) = xc + a*cos(theta)*cos(phi) - b*sin(theta)*sin(phi) // y(theta) = yc + a*cos(theta)*sin(phi) + b*sin(theta)*cos(phi) double a (aoe->major / 2.0), b (aoe->minor / 2.0), phi (aoe->angle), xc (aoe->center.fX), yc (aoe->center.fY); if (a == 0 || b == 0) { // Degenerate case - TODO: handle as line instead of throwing throw Base::Exception("Ellipse with invalid major axis in GeometryObject::boundingBoxOfAoe()"); } // Calculate points of interest for the bounding box. These are points // where d(x)/d(theta) and d(y)/d(theta) = 0 (where the x and y extremes // of the ellipse would be if it were complete), and arc endpoints. double testAngles[6] = { atan(tan(phi) * (-b / a)), testAngles[0] + M_PI }; if (tan(phi) == 0) { testAngles[2] = M_PI / 2.0; testAngles[3] = 3.0 * M_PI / 2.0; } else { testAngles[2] = atan((1.0 / tan(phi)) * (b / a)); testAngles[3] = testAngles[2] + M_PI; } testAngles[4] = start; testAngles[5] = end; // Add extremes to bounding box, if they are within the arc Base::BoundBox3d bb; for (int ai(0); ai < 6; ++ai) { double theta(testAngles[ai]); if (isWithinArc(theta, start, end, cw) ) { bb.Add( Base::Vector3d(xc + a*cos(theta)*cos(phi) - b*sin(theta)*sin(phi), yc + a*cos(theta)*sin(phi) - b*sin(theta)*cos(phi), 0) ); } } return bb; }
PointsGrid::PointsGrid (const PointKernel &rclM, double fGridLen) : _pclPoints(&rclM), _ulCtElements(0), _ulCtGridsX(0), _ulCtGridsY(0), _ulCtGridsZ(0), _fGridLenX(0.0f), _fGridLenY(0.0f), _fGridLenZ(0.0f), _fMinX(0.0f), _fMinY(0.0f), _fMinZ(0.0f) { Base::BoundBox3d clBBPts;// = _pclPoints->GetBoundBox(); for (PointKernel::const_iterator it = _pclPoints->begin(); it != _pclPoints->end(); ++it ) clBBPts.Add(*it); Rebuild(std::max<unsigned long>((unsigned long)(clBBPts.LengthX() / fGridLen), 1), std::max<unsigned long>((unsigned long)(clBBPts.LengthY() / fGridLen), 1), std::max<unsigned long>((unsigned long)(clBBPts.LengthZ() / fGridLen), 1)); }
void PointsGrid::InitGrid (void) { assert(_pclPoints != NULL); unsigned long i, j; // Grid Laengen berechnen wenn nicht initialisiert // if ((_ulCtGridsX == 0) || (_ulCtGridsY == 0) || (_ulCtGridsZ == 0)) CalculateGridLength(POINTS_CT_GRID, POINTS_MAX_GRIDS); // Grid Laengen und Offset bestimmen // { Base::BoundBox3d clBBPts;// = _pclPoints->GetBoundBox(); for (PointKernel::const_iterator it = _pclPoints->begin(); it != _pclPoints->end(); ++it ) clBBPts.Add(*it); double fLengthX = clBBPts.LengthX(); double fLengthY = clBBPts.LengthY(); double fLengthZ = clBBPts.LengthZ(); { // Offset fGridLen/2 // _fGridLenX = (1.0f + fLengthX) / double(_ulCtGridsX); _fMinX = clBBPts.MinX - 0.5f; } { _fGridLenY = (1.0f + fLengthY) / double(_ulCtGridsY); _fMinY = clBBPts.MinY - 0.5f; } { _fGridLenZ = (1.0f + fLengthZ) / double(_ulCtGridsZ); _fMinZ = clBBPts.MinZ - 0.5f; } } // Daten-Struktur anlegen _aulGrid.clear(); _aulGrid.resize(_ulCtGridsX); for (i = 0; i < _ulCtGridsX; i++) { _aulGrid[i].resize(_ulCtGridsY); for (j = 0; j < _ulCtGridsY; j++) _aulGrid[i][j].resize(_ulCtGridsZ); } }
Base::BoundBox3d PointKernel::getBoundBox(void)const { Base::BoundBox3d bnd; //FIXME: VS 2015 or later causes a linker error #if defined _WIN32 // Thread-local bounding boxes Concurrency::combinable<Base::BoundBox3d> bbs; // Cannot use a const_point_iterator here as it is *not* a proper iterator (fails the for_each template) Concurrency::parallel_for_each(_Points.begin(), _Points.end(), [this, &bbs](const value_type& value) { Base::Vector3d vertd(value.x, value.y, value.z); bbs.local().Add(this->_Mtrx * vertd); }); // Combine each thread-local bounding box in the final bounding box bbs.combine_each([&bnd](const Base::BoundBox3d& lbb) { bnd.Add(lbb); }); #else for (const_point_iterator it = begin(); it != end(); ++it) bnd.Add(*it); #endif return bnd; }
void CmdPartCrossSections::activated(int iMsg) { Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); if (!dlg) { std::vector<App::DocumentObject*> obj = Gui::Selection().getObjectsOfType (Part::Feature::getClassTypeId()); Base::BoundBox3d bbox; for (std::vector<App::DocumentObject*>::iterator it = obj.begin(); it != obj.end(); ++it) { bbox.Add(static_cast<Part::Feature*>(*it)->Shape.getBoundingBox()); } dlg = new PartGui::TaskCrossSections(bbox); } Gui::Control().showDialog(dlg); }
void PointsGrid::CalculateGridLength (unsigned long ulCtGrid, unsigned long ulMaxGrids) { // Grid Laengen bzw. Anzahl der Grids pro Dimension berechnen // pro Grid sollen ca. 10 (?!?!) Facets liegen // bzw. max Grids sollten 10000 nicht ueberschreiten Base::BoundBox3d clBBPtsEnlarged;// = _pclPoints->GetBoundBox(); for (PointKernel::const_iterator it = _pclPoints->begin(); it != _pclPoints->end(); ++it ) clBBPtsEnlarged.Add(*it); double fVolElem; if (_ulCtElements > (ulMaxGrids * ulCtGrid)) fVolElem = (clBBPtsEnlarged.LengthX() * clBBPtsEnlarged.LengthY() * clBBPtsEnlarged.LengthZ()) / float(ulMaxGrids * ulCtGrid); else fVolElem = (clBBPtsEnlarged.LengthX() * clBBPtsEnlarged.LengthY() * clBBPtsEnlarged.LengthZ()) / float(_ulCtElements); double fVol = fVolElem * float(ulCtGrid); double fGridLen = float(pow((float)fVol,(float) 1.0f / 3.0f)); _ulCtGridsX = std::max<unsigned long>((unsigned long)(clBBPtsEnlarged.LengthX() / fGridLen), 1); _ulCtGridsY = std::max<unsigned long>((unsigned long)(clBBPtsEnlarged.LengthY() / fGridLen), 1); _ulCtGridsZ = std::max<unsigned long>((unsigned long)(clBBPtsEnlarged.LengthZ() / fGridLen), 1); }
Base::BoundBox3d GeometryObject::calcBoundingBox() const { Base::BoundBox3d bbox; // First calculate bounding box based on vertices for(std::vector<Vertex *>::const_iterator it( vertexGeom.begin() ); it != vertexGeom.end(); ++it) { bbox.Add( Base::Vector3d((*it)->pnt.fX, (*it)->pnt.fY, 0.) ); } // Now, consider geometry where vertices don't define bounding box eg circles for (std::vector<BaseGeom *>::const_iterator it( edgeGeom.begin() ); it != edgeGeom.end(); ++it) { switch ((*it)->geomType) { case CIRCLE: { Circle *c = static_cast<Circle *>(*it); bbox.Add( Base::BoundBox3d(-c->radius + c->center.fX, -c->radius + c->center.fY, 0, c->radius + c->center.fX, c->radius + c->center.fY, 0) ); } break; case ARCOFCIRCLE: { AOC *arc = static_cast<AOC *>(*it); // Endpoints of arc bbox.Add( Base::Vector3d(arc->radius * cos(arc->startAngle), arc->radius * sin(arc->startAngle), 0.0) ); bbox.Add( Base::Vector3d(arc->radius * cos(arc->endAngle), arc->radius * sin(arc->endAngle), 0.0) ); // Extreme X and Y values if they're within the arc for (double theta = 0.0; theta < 6.5; theta += M_PI / 2.0) { if (isWithinArc(theta, arc->startAngle, arc->endAngle, arc->cw)) { bbox.Add( Base::Vector3d(arc->radius * cos(theta), arc->radius * sin(theta), 0.0) ); } } } break; case ELLIPSE: { bbox.Add( boundingBoxOfAoe(static_cast<Ellipse *>(*it)) ); } break; case ARCOFELLIPSE: { AOE *aoe = static_cast<AOE *>(*it); double start = aoe->startAngle, end = aoe->endAngle; bool cw = aoe->cw; bbox.Add( boundingBoxOfAoe(static_cast<Ellipse *>(*it), start, end, cw) ); } break; case BSPLINE: { bbox.Add( boundingBoxOfBspline(static_cast<BSpline *>(*it)) ); } break; case GENERIC: { // this case ends up just drawing line segments between points Generic *gen = static_cast<Generic *>(*it); for (std::vector<Base::Vector2D>::const_iterator segIt = gen->points.begin(); segIt != gen->points.end(); ++segIt) { bbox.Add( Base::Vector3d(segIt->fX, segIt->fY, 0) ); } } break; default: throw Base::Exception("Unknown geomType in GeometryObject::calcBoundingBox()"); } } return bbox; }
Base::BoundBox3d GeometryObject::boundingBoxOfBspline(const BSpline *spline) const { Base::BoundBox3d bb; for (std::vector<BezierSegment>::const_iterator segItr( spline->segments.begin() ); segItr != spline->segments.end(); ++segItr) { switch (segItr->poles) { case 0: // Degenerate, but safe ignore break; case 2: // Degenerate - straight line bb.Add(Base::Vector3d( segItr->pnts[1].fX, segItr->pnts[1].fY, 0 )); // fall through case 1: // Degenerate - just a point bb.Add(Base::Vector3d( segItr->pnts[0].fX, segItr->pnts[0].fY, 0 )); break; case 3: { double px[3] = { segItr->pnts[0].fX, segItr->pnts[1].fX, segItr->pnts[2].fX }, py[3] = { segItr->pnts[0].fY, segItr->pnts[1].fY, segItr->pnts[2].fY }, slns[4] = { 0, 1 }; // Consider the segment's end points // if's are to prevent problems with divide-by-0 if ((2 * px[1] - px[0] - px[2]) == 0) { slns[2] = -1; } else { slns[2] = (px[1] - px[0]) / (2 * px[1] - px[0] - px[2]); } if ((2 * py[1] - py[0] - py[2]) == 0) { slns[3] = -1; } else { slns[3] = (py[1] - py[0]) / (2 * py[1] - py[0] - py[2]); } // evaluate B(t) at the endpoints and zeros for (int s(0); s < 4; ++s) { double t( slns[s] ); if (t < 0 || t > 1) { continue; } double tx( px[0] * (1 - t) * (1 - t) + px[1] * 2 * (1 - t) * t + px[2] * t * t ), ty( py[0] * (1 - t) * (1 - t) + py[1] * 2 * (1 - t) * t + py[2] * t * t ); bb.Add( Base::Vector3d(tx, ty, 0) ); } } break; case 4: { double px[4] = { segItr->pnts[0].fX, segItr->pnts[1].fX, segItr->pnts[2].fX, segItr->pnts[3].fX }, py[4] = { segItr->pnts[0].fY, segItr->pnts[1].fY, segItr->pnts[2].fY, segItr->pnts[3].fY }, // If B(t) is the cubic Bezier, find t where B'(t) == 0 // // For control points P0-P3, B'(t) works out to be: // B'(t) = t^2 * (-3P0 + 9P1 - 9P2 + 3P3) + // t * (6P0 - 12P1 + 6P2) + // 3 * (P1 - P0) // // So, we use the quadratic formula! ax = -3 * px[0] + 9 * px[1] - 9 * px[2] + 3 * px[3], ay = -3 * py[0] + 9 * py[1] - 9 * py[2] + 3 * py[3], bx = 6 * px[0] - 12 * px[1] + 6 * px[2], by = 6 * py[0] - 12 * py[1] + 6 * py[2], cx = 3 * px[1] - 3 * px[0], cy = 3 * py[1] - 3 * py[0], slns[6] = { 0, 1 }; // Consider the segment's end points // if's are to prevent problems with divide-by-0 and NaN if ( (2 * ax) == 0 || (bx * bx - 4 * ax * cx) < 0 ) { slns[2] = -1; slns[3] = -1; } else { slns[2] = (-bx + sqrt(bx * bx - 4 * ax * cx)) / (2 * ax); slns[3] = (-bx - sqrt(bx * bx - 4 * ax * cx)) / (2 * ax); } if ((2 * ay) == 0 || (by * by - 4 * ay * cy) < 0 ) { slns[4] = -1; slns[5] = -1; } else { slns[4] = (-by + sqrt(by * by - 4 * ay * cy)) / (2 * ay); slns[5] = (-by - sqrt(by * by - 4 * ay * cy)) / (2 * ay); } // evaluate B(t) at the endpoints and zeros for (int s(0); s < 6; ++s) { double t( slns[s] ); if (t < 0 || t > 1) { continue; } double tx( px[0] * (1 - t) * (1 - t) * (1 - t) + px[1] * 3 * (1 - t) * (1 - t) * t + px[2] * 3 * (1 - t) * t * t + px[3] * t * t * t ), ty( py[0] * (1 - t) * (1 - t) * (1 - t) + py[1] * 3 * (1 - t) * (1 - t) * t + py[2] * 3 * (1 - t) * t * t + py[3] * t * t * t ); bb.Add( Base::Vector3d(tx, ty, 0) ); } } break; default: throw Base::Exception("Invalid degree bezier segment in GeometryObject::calcBoundingBox"); } } return bb; }
void PointsGrid::CalculateGridLength (int iCtGridPerAxis) { if (iCtGridPerAxis<=0) { CalculateGridLength(POINTS_CT_GRID, POINTS_MAX_GRIDS); return; } // Grid Laengen bzw. Anzahl der Grids pro Dimension berechnen // pro Grid sollen ca. 10 (?!?!) Facets liegen // bzw. max Grids sollten 10000 nicht ueberschreiten Base::BoundBox3d clBBPts;// = _pclPoints->GetBoundBox(); for (PointKernel::const_iterator it = _pclPoints->begin(); it != _pclPoints->end(); ++it ) clBBPts.Add(*it); double fLenghtX = clBBPts.LengthX(); double fLenghtY = clBBPts.LengthY(); double fLenghtZ = clBBPts.LengthZ(); double fLenghtD = clBBPts.CalcDiagonalLength(); double fLengthTol = 0.05f * fLenghtD; bool bLenghtXisZero = (fLenghtX <= fLengthTol); bool bLenghtYisZero = (fLenghtY <= fLengthTol); bool bLenghtZisZero = (fLenghtZ <= fLengthTol); int iFlag = 0; int iMaxGrids = 1; if (bLenghtXisZero) iFlag += 1; else iMaxGrids *= iCtGridPerAxis; if (bLenghtYisZero) iFlag += 2; else iMaxGrids *= iCtGridPerAxis; if (bLenghtZisZero) iFlag += 4; else iMaxGrids *= iCtGridPerAxis; unsigned long ulGridsFacets = 10; double fFactorVolumen = 40.0; double fFactorArea = 10.0; switch (iFlag) { case 0: { double fVolumen = fLenghtX * fLenghtY * fLenghtZ; double fVolumenGrid = (fVolumen * ulGridsFacets) / (fFactorVolumen * _ulCtElements); if ((fVolumenGrid * iMaxGrids) < fVolumen) fVolumenGrid = fVolumen / (float)iMaxGrids; double fLengthGrid = float(pow((float)fVolumenGrid,(float) 1.0f / 3.0f)); _ulCtGridsX = std::max<unsigned long>((unsigned long)(fLenghtX / fLengthGrid), 1); _ulCtGridsY = std::max<unsigned long>((unsigned long)(fLenghtY / fLengthGrid), 1); _ulCtGridsZ = std::max<unsigned long>((unsigned long)(fLenghtZ / fLengthGrid), 1); } break; case 1: { _ulCtGridsX = 1; // bLenghtXisZero double fArea = fLenghtY * fLenghtZ; double fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements); if ((fAreaGrid * iMaxGrids) < fArea) fAreaGrid = fArea / (double)iMaxGrids; double fLengthGrid = double(sqrt(fAreaGrid)); _ulCtGridsY = std::max<unsigned long>((unsigned long)(fLenghtY / fLengthGrid), 1); _ulCtGridsZ = std::max<unsigned long>((unsigned long)(fLenghtZ / fLengthGrid), 1); } break; case 2: { _ulCtGridsY = 1; // bLenghtYisZero double fArea = fLenghtX * fLenghtZ; double fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements); if ((fAreaGrid * iMaxGrids) < fArea) fAreaGrid = fArea / (double)iMaxGrids; double fLengthGrid = double(sqrt(fAreaGrid)); _ulCtGridsX = std::max<unsigned long>((unsigned long)(fLenghtX / fLengthGrid), 1); _ulCtGridsZ = std::max<unsigned long>((unsigned long)(fLenghtZ / fLengthGrid), 1); } break; case 3: { _ulCtGridsX = 1; // bLenghtXisZero _ulCtGridsY = 1; // bLenghtYisZero _ulCtGridsZ = iMaxGrids; // bLenghtYisZero } break; case 4: { _ulCtGridsZ = 1; // bLenghtZisZero double fArea = fLenghtX * fLenghtY; double fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements); if ((fAreaGrid * iMaxGrids) < fArea) fAreaGrid = fArea / (float)iMaxGrids; double fLengthGrid = double(sqrt(fAreaGrid)); _ulCtGridsX = std::max<unsigned long>((unsigned long)(fLenghtX / fLengthGrid), 1); _ulCtGridsY = std::max<unsigned long>((unsigned long)(fLenghtY / fLengthGrid), 1); } break; case 5: { _ulCtGridsX = 1; // bLenghtXisZero _ulCtGridsZ = 1; // bLenghtZisZero _ulCtGridsY = iMaxGrids; // bLenghtYisZero } break; case 6: { _ulCtGridsY = 1; // bLenghtYisZero _ulCtGridsZ = 1; // bLenghtZisZero _ulCtGridsX = iMaxGrids; // bLenghtYisZero } break; case 7: { _ulCtGridsX = iMaxGrids; // bLenghtXisZero _ulCtGridsY = iMaxGrids; // bLenghtYisZero _ulCtGridsZ = iMaxGrids; // bLenghtZisZero } break; } }