[TD]fix autoscale for DPG
This commit is contained in:
@@ -60,7 +60,8 @@ const char* DrawProjGroup::ProjectionTypeEnums[] = {"Default",
|
||||
|
||||
PROPERTY_SOURCE(TechDraw::DrawProjGroup, TechDraw::DrawViewCollection)
|
||||
|
||||
DrawProjGroup::DrawProjGroup(void)
|
||||
DrawProjGroup::DrawProjGroup(void) :
|
||||
m_lockScale(false)
|
||||
{
|
||||
static const char *group = "Base";
|
||||
static const char *agroup = "Distribute";
|
||||
@@ -97,20 +98,12 @@ void DrawProjGroup::onChanged(const App::Property* prop)
|
||||
TechDraw::DrawPage *page = getPage();
|
||||
if (!isRestoring() && page) {
|
||||
if (prop == &Source) {
|
||||
// std::vector<App::DocumentObject*> sourceObjs = Source.getValues();
|
||||
// if (!sourceObjs.empty()) {
|
||||
// if (!hasAnchor()) {
|
||||
// // if we have a Source, but no Anchor, make an anchor
|
||||
// Anchor.setValue(addProjection("Front")); //<<<<< semi-loop here!
|
||||
// //add projection marks object as changed -> onChanged, but anchor value isn't set
|
||||
// Anchor.purgeTouched(); //don't need to mark this
|
||||
// }
|
||||
// } else {
|
||||
// //Source has been changed to null! Why? What to do?
|
||||
// }
|
||||
//nothing in particular
|
||||
}
|
||||
if (prop == &Scale) {
|
||||
updateChildrenScale();
|
||||
if (!m_lockScale) {
|
||||
updateChildrenScale();
|
||||
}
|
||||
}
|
||||
|
||||
if (prop == &ProjectionType) {
|
||||
@@ -128,11 +121,7 @@ void DrawProjGroup::onChanged(const App::Property* prop)
|
||||
if (prop == &ScaleType) {
|
||||
double newScale = getScale();
|
||||
if (ScaleType.isValue("Automatic")) {
|
||||
//Recalculate scale if Group is too big or too small!
|
||||
newScale = calculateAutomaticScale();
|
||||
if(std::abs(getScale() - newScale) > FLT_EPSILON) {
|
||||
Scale.setValue(newScale);
|
||||
}
|
||||
//Nothing in particular
|
||||
} else if (ScaleType.isValue("Page")) {
|
||||
newScale = page->Scale.getValue();
|
||||
if(std::abs(getScale() - newScale) > FLT_EPSILON) {
|
||||
@@ -176,8 +165,18 @@ App::DocumentObjectExecReturn *DrawProjGroup::execute(void)
|
||||
return DrawViewCollection::execute();
|
||||
}
|
||||
|
||||
autoPositionChildren();
|
||||
if (ScaleType.isValue("Automatic")) {
|
||||
if (!checkFit()) {
|
||||
double newScale = autoScale();
|
||||
m_lockScale = true;
|
||||
Scale.setValue(newScale);
|
||||
Scale.purgeTouched();
|
||||
updateChildrenScale();
|
||||
m_lockScale = false;
|
||||
}
|
||||
}
|
||||
|
||||
autoPositionChildren();
|
||||
return DrawViewCollection::execute();
|
||||
}
|
||||
|
||||
@@ -219,6 +218,7 @@ Base::BoundBox3d DrawProjGroup::getBoundingBox() const
|
||||
|
||||
bb.ScaleX(1. / part->getScale());
|
||||
bb.ScaleY(1. / part->getScale());
|
||||
bb.ScaleZ(1. / part->getScale());
|
||||
|
||||
// X and Y of dependent views are relative to the anchorView
|
||||
if (part != anchorView) {
|
||||
@@ -237,6 +237,7 @@ TechDraw::DrawPage * DrawProjGroup::getPage(void) const
|
||||
return findParentPage();
|
||||
}
|
||||
|
||||
// obs? replaced by autoscale?
|
||||
// Function provided by Joe Dowsett, 2014
|
||||
double DrawProjGroup::calculateAutomaticScale() const
|
||||
{
|
||||
@@ -248,15 +249,14 @@ double DrawProjGroup::calculateAutomaticScale() const
|
||||
|
||||
arrangeViewPointers(viewPtrs);
|
||||
double width, height;
|
||||
minimumBbViews(viewPtrs, width, height); //get 1:1 bbxs
|
||||
// if Page.keepUpdated is false, and DrawViews have never been executed,
|
||||
// bb's will be 0x0 and this routine will return 0!!!
|
||||
// if we return 1.0, AutoScale will sort itself out once bb's are non-zero.
|
||||
minimumBbViews(viewPtrs, width, height); //get SCALED boxes!
|
||||
// if Page.keepUpdated is false, and DrawViews have never been executed,
|
||||
// bb's will be 0x0 and this routine will return 0!!!
|
||||
// if we return 1.0, AutoScale will sort itself out once bb's are non-zero.
|
||||
double bbFudge = 1.2;
|
||||
width *= bbFudge;
|
||||
height *= bbFudge;
|
||||
|
||||
|
||||
// C++ Standard says casting bool to int gives 0 or 1
|
||||
int numVertSpaces = (viewPtrs[0] || viewPtrs[3] || viewPtrs[7]) +
|
||||
(viewPtrs[2] || viewPtrs[5] || viewPtrs[9]) +
|
||||
@@ -284,26 +284,36 @@ double DrawProjGroup::calculateAutomaticScale() const
|
||||
return result;
|
||||
}
|
||||
|
||||
//returns the (scaled) bounding rectangle of all the views.
|
||||
QRectF DrawProjGroup::getRect() const //this is current rect, not potential rect
|
||||
{
|
||||
// Base::Console().Message("DPG::getRect - views: %d\n", Views.getValues().size());
|
||||
DrawProjGroupItem *viewPtrs[10];
|
||||
arrangeViewPointers(viewPtrs);
|
||||
double width, height;
|
||||
minimumBbViews(viewPtrs, width, height); // w,h of just the views at 1:1 scale
|
||||
minimumBbViews(viewPtrs, width, height); //this is scaled!
|
||||
double xSpace = spacingX.getValue() * 3.0 * std::max(1.0,getScale());
|
||||
double ySpace = spacingY.getValue() * 2.0 * std::max(1.0,getScale());
|
||||
double rectW = getScale() * width + xSpace; //scale the 1:1 w,h and add whitespace
|
||||
double rectH = getScale() * height + ySpace;
|
||||
double rectW = 0.0;
|
||||
double rectH = 0.0;
|
||||
if ( !(DrawUtil::fpCompare(width, 0.0) &&
|
||||
DrawUtil::fpCompare(height, 0.0)) ) {
|
||||
rectW = width + xSpace;
|
||||
rectH = height + ySpace;
|
||||
}
|
||||
double fudge = 1.3; //make rect a little big to make sure it fits
|
||||
rectW *= fudge;
|
||||
rectH *= fudge;
|
||||
return QRectF(0,0,rectW,rectH);
|
||||
}
|
||||
|
||||
//find area consumed by Views only in 1:1 Scale
|
||||
//find area consumed by Views only in current scale
|
||||
void DrawProjGroup::minimumBbViews(DrawProjGroupItem *viewPtrs[10],
|
||||
double &width, double &height) const
|
||||
{
|
||||
// Get bounding boxes in object scale
|
||||
Base::BoundBox3d bboxes[10];
|
||||
makeViewBbs(viewPtrs, bboxes, true);
|
||||
makeViewBbs(viewPtrs, bboxes, true); //true => scaled
|
||||
|
||||
//TODO: note that TLF/TRF/BLF,BRF extend a bit farther than a strict row/col arrangement would suggest.
|
||||
//get widest view in each row/column
|
||||
@@ -607,6 +617,7 @@ gp_Dir DrawProjGroup::vec2dir(Base::Vector3d v)
|
||||
return result;
|
||||
}
|
||||
|
||||
//this can be improved. this implementation positions views too far apart.
|
||||
Base::Vector3d DrawProjGroup::getXYPosition(const char *viewTypeCStr)
|
||||
{
|
||||
Base::Vector3d result(0.0,0.0,0.0);
|
||||
@@ -635,14 +646,14 @@ Base::Vector3d DrawProjGroup::getXYPosition(const char *viewTypeCStr)
|
||||
|
||||
// Calculate bounding boxes for each displayed view
|
||||
Base::BoundBox3d bboxes[10];
|
||||
makeViewBbs(viewPtrs, bboxes);
|
||||
makeViewBbs(viewPtrs, bboxes); //scaled
|
||||
|
||||
double xSpacing = spacingX.getValue(); //in mm/scale
|
||||
double ySpacing = spacingY.getValue(); //in mm/scale
|
||||
double xSpacing = spacingX.getValue(); //in mm, no scale
|
||||
double ySpacing = spacingY.getValue(); //in mm, no scale
|
||||
|
||||
double bigRow = 0.0;
|
||||
double bigCol = 0.0;
|
||||
for (auto& b: bboxes) {
|
||||
for (auto& b: bboxes) { //space based on width/height of biggest view
|
||||
if (!b.IsValid()) {
|
||||
continue;
|
||||
}
|
||||
@@ -659,6 +670,7 @@ Base::Vector3d DrawProjGroup::getXYPosition(const char *viewTypeCStr)
|
||||
bigCol = std::max(bigCol,bigRow);
|
||||
bigRow = bigCol;
|
||||
}
|
||||
//TODO: find biggest for each row/column and adjust calculation to use bigCol[i], bigRow[j] ?????
|
||||
|
||||
if (viewPtrs[0] && //iso
|
||||
bboxes[0].IsValid()) {
|
||||
@@ -791,7 +803,7 @@ int DrawProjGroup::getViewIndex(const char *viewTypeCStr) const
|
||||
void DrawProjGroup::arrangeViewPointers(DrawProjGroupItem *viewPtrs[10]) const
|
||||
{
|
||||
for (int i=0; i<10; ++i) {
|
||||
viewPtrs[i] = NULL;
|
||||
viewPtrs[i] = nullptr;
|
||||
}
|
||||
|
||||
// Determine layout - should be either "First Angle" or "Third Angle"
|
||||
@@ -871,7 +883,9 @@ void DrawProjGroup::makeViewBbs(DrawProjGroupItem *viewPtrs[10],
|
||||
Base::BoundBox3d bboxes[10],
|
||||
bool documentScale) const
|
||||
{
|
||||
for (int i = 0; i < 10; ++i)
|
||||
Base::BoundBox3d empty(Base::Vector3d(0.0, 0.0, 0.0), 0.0);
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
bboxes[i] = empty;
|
||||
if (viewPtrs[i]) {
|
||||
bboxes[i] = viewPtrs[i]->getBoundingBox();
|
||||
if (!documentScale) {
|
||||
@@ -880,12 +894,8 @@ void DrawProjGroup::makeViewBbs(DrawProjGroupItem *viewPtrs[10],
|
||||
bboxes[i].ScaleY(scale);
|
||||
bboxes[i].ScaleZ(scale);
|
||||
}
|
||||
} else {
|
||||
// BoundBox3d defaults to length=(FLOAT_MAX + -FLOAT_MAX)
|
||||
bboxes[i].ScaleX(0);
|
||||
bboxes[i].ScaleY(0);
|
||||
bboxes[i].ScaleZ(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawProjGroup::recomputeChildren(void)
|
||||
@@ -928,6 +938,7 @@ void DrawProjGroup::updateChildrenScale(void)
|
||||
throw Base::TypeError("Error: projection in DPG list is not a DPGI!");
|
||||
} else if(view->Scale.getValue()!=Scale.getValue()) {
|
||||
view->Scale.setValue(Scale.getValue());
|
||||
view->recomputeFeature();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -982,34 +993,6 @@ void DrawProjGroup::updateChildrenEnforce(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* check if ProjectionGroup fits on Page
|
||||
*/
|
||||
bool DrawProjGroup::checkFit(TechDraw::DrawPage* p) const
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
QRectF viewBox = getRect();
|
||||
double fudge = 1.1;
|
||||
double maxWidth = viewBox.width() * fudge;
|
||||
double maxHeight = viewBox.height() * fudge;
|
||||
|
||||
if ( (maxWidth > p->getPageWidth()) ||
|
||||
(maxHeight > p->getPageHeight()) ) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
if (ScaleType.isValue("Automatic")) { //expand if too small
|
||||
double magnifyLimit = 0.60;
|
||||
if ( (maxWidth < p->getPageWidth() * magnifyLimit) &&
|
||||
(maxHeight < p->getPageHeight() * magnifyLimit) ) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
App::Enumeration DrawProjGroup::usedProjectionType(void)
|
||||
{
|
||||
//TODO: Would've been nice to have an Enumeration(const PropertyEnumeration &) constructor
|
||||
|
||||
@@ -69,7 +69,6 @@ public:
|
||||
Base::BoundBox3d getBoundingBox() const;
|
||||
double calculateAutomaticScale() const;
|
||||
virtual QRectF getRect(void) const override;
|
||||
virtual bool checkFit(TechDraw::DrawPage* p) const override;
|
||||
/// Check if container has a view of a specific type
|
||||
bool hasProjection(const char *viewProjType) const;
|
||||
|
||||
@@ -175,7 +174,8 @@ protected:
|
||||
gp_Dir vec2dir(Base::Vector3d v);
|
||||
|
||||
virtual void handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property * prop) override;
|
||||
|
||||
|
||||
bool m_lockScale;
|
||||
};
|
||||
|
||||
} //namespace TechDraw
|
||||
|
||||
@@ -85,6 +85,9 @@ public:
|
||||
void autoPosition(void);
|
||||
bool isAnchor(void) const;
|
||||
|
||||
//DPGI always fits on page since DPG handles scaling
|
||||
virtual bool checkFit(void) const override { return true; }
|
||||
virtual bool checkFit(DrawPage*) const override { return true; }
|
||||
|
||||
protected:
|
||||
void onChanged(const App::Property* prop) override;
|
||||
|
||||
@@ -262,30 +262,60 @@ DrawViewClip* DrawView::getClipGroup(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
double DrawView::autoScale(double w, double h) const
|
||||
double DrawView::autoScale(void) const
|
||||
{
|
||||
double fudgeFactor = 0.90;
|
||||
QRectF viewBox = getRect();
|
||||
auto page = findParentPage();
|
||||
double w = page->getPageWidth();
|
||||
double h = page->getPageHeight();
|
||||
return autoScale(w,h);
|
||||
}
|
||||
|
||||
//compare 1:1 rect of view to pagesize(pw,h)
|
||||
double DrawView::autoScale(double pw, double ph) const
|
||||
{
|
||||
// Base::Console().Message("DV::autoScale(Page: %.3f, %.3f) - %s\n", pw, ph, getNameInDocument());
|
||||
double fudgeFactor = 1.0; //make it a bit smaller just in case.
|
||||
QRectF viewBox = getRect(); //getRect is scaled (ie current actual size)
|
||||
if (!viewBox.isValid()) {
|
||||
return 1.0;
|
||||
}
|
||||
//have to unscale rect to determine new scale
|
||||
double vbw = viewBox.width()/getScale();
|
||||
double vbh = viewBox.height()/getScale();
|
||||
double xScale = w/vbw;
|
||||
double yScale = h/vbh;
|
||||
//TODO: find a standard scale that's close? 1:2, 1:10, 1:100...? Logic in TaskProjGroup
|
||||
double newScale = fudgeFactor * std::min(xScale,yScale);
|
||||
newScale = DrawUtil::sensibleScale(newScale);
|
||||
return newScale;
|
||||
double xScale = pw/vbw; // > 1 page bigger than figure
|
||||
double yScale = ph/vbh; // < 1 page is smaller than figure
|
||||
double newScale = std::min(xScale,yScale) * fudgeFactor;
|
||||
double sensibleScale = DrawUtil::sensibleScale(newScale);
|
||||
return sensibleScale;
|
||||
}
|
||||
|
||||
//!check if View fits on Page
|
||||
bool DrawView::checkFit(void) const
|
||||
{
|
||||
auto page = findParentPage();
|
||||
return checkFit(page);
|
||||
}
|
||||
|
||||
//!check if View is too big for page
|
||||
//should check if unscaled rect is too big for page
|
||||
bool DrawView::checkFit(TechDraw::DrawPage* p) const
|
||||
{
|
||||
bool result = true;
|
||||
QRectF viewBox = getRect();
|
||||
if ( (viewBox.width() > p->getPageWidth()) ||
|
||||
(viewBox.height() > p->getPageHeight()) ) {
|
||||
result = false;
|
||||
double fudge = 1.1;
|
||||
|
||||
double width = 0.0;
|
||||
double height = 0.0;
|
||||
QRectF viewBox = getRect(); //rect is scaled
|
||||
if (!viewBox.isValid()) {
|
||||
result = true;
|
||||
} else {
|
||||
width = viewBox.width() / getScale(); //unscaled rect w x h
|
||||
height = viewBox.height() / getScale();
|
||||
width *= fudge;
|
||||
height *= fudge;
|
||||
if ( (width > p->getPageWidth()) ||
|
||||
(height > p->getPageHeight()) ) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,9 @@ public:
|
||||
|
||||
virtual DrawPage* findParentPage() const;
|
||||
virtual QRectF getRect() const; //must be overridden by derived class
|
||||
virtual double autoScale(void) const;
|
||||
virtual double autoScale(double w, double h) const;
|
||||
virtual bool checkFit(void) const;
|
||||
virtual bool checkFit(DrawPage*) const;
|
||||
virtual void setPosition(double x, double y, bool force = false);
|
||||
bool keepUpdated(void);
|
||||
@@ -106,8 +108,6 @@ protected:
|
||||
int prefScaleType(void);
|
||||
double prefScale(void);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
static const char* ScaleTypeEnums[];
|
||||
static App::PropertyFloatConstraint::Constraints scaleRange;
|
||||
|
||||
@@ -167,6 +167,8 @@ DrawViewPart::DrawViewPart(void) :
|
||||
|
||||
geometryObject = nullptr;
|
||||
getRunControl();
|
||||
//initialize bbox to non-garbage
|
||||
bbox = Base::BoundBox3d(Base::Vector3d(0.0, 0.0, 0.0), 0.0);
|
||||
}
|
||||
|
||||
DrawViewPart::~DrawViewPart()
|
||||
@@ -254,33 +256,32 @@ App::DocumentObjectExecReturn *DrawViewPart::execute(void)
|
||||
XDirection.purgeTouched(); //don't trigger updates!
|
||||
//unblock
|
||||
}
|
||||
|
||||
// m_saveShape = shape;
|
||||
geometryObject = makeGeometryForShape(shape);
|
||||
|
||||
#if MOD_TECHDRAW_HANDLE_FACES
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
if (handleFaces() && !geometryObject->usePolygonHLR()) {
|
||||
try {
|
||||
extractFaces();
|
||||
}
|
||||
catch (Standard_Failure& e4) {
|
||||
Base::Console().Log("LOG - DVP::execute - extractFaces failed for %s - %s **\n",getNameInDocument(),e4.GetMessageString());
|
||||
return new App::DocumentObjectExecReturn(e4.GetMessageString());
|
||||
|
||||
m_saveShape = shape;
|
||||
buildGeometry(shape);
|
||||
|
||||
//second pass if required
|
||||
if (ScaleType.isValue("Automatic")) {
|
||||
if (!checkFit()) {
|
||||
double newScale = autoScale();
|
||||
Scale.setValue(newScale);
|
||||
Scale.purgeTouched();
|
||||
if (geometryObject != nullptr) {
|
||||
delete geometryObject;
|
||||
geometryObject = nullptr;
|
||||
buildGeometry(shape);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addCosmeticVertexesToGeom();
|
||||
addCosmeticEdgesToGeom();
|
||||
addCenterLinesToGeom();
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto diff = end - start;
|
||||
double diffOut = std::chrono::duration <double, std::milli> (diff).count();
|
||||
Base::Console().Log("TIMING - %s DVP spent: %.3f millisecs handling Faces\n",
|
||||
getNameInDocument(),diffOut);
|
||||
|
||||
#endif //#if MOD_TECHDRAW_HANDLE_FACES
|
||||
//#endif //#if MOD_TECHDRAW_HANDLE_FACES
|
||||
// Base::Console().Message("DVP::execute - exits\n");
|
||||
return DrawView::execute();
|
||||
}
|
||||
@@ -318,6 +319,28 @@ void DrawViewPart::onChanged(const App::Property* prop)
|
||||
//TODO: when scale changes, any Dimensions for this View sb recalculated. DVD should pick this up subject to topological naming issues.
|
||||
}
|
||||
|
||||
void DrawViewPart::buildGeometry(TopoDS_Shape shape)
|
||||
{
|
||||
// Base::Console().Message("DVP::buildGeometry()\n");
|
||||
geometryObject = makeGeometryForShape(shape);
|
||||
|
||||
#if MOD_TECHDRAW_HANDLE_FACES
|
||||
// auto start = std::chrono::high_resolution_clock::now();
|
||||
if (handleFaces() && !geometryObject->usePolygonHLR()) {
|
||||
try {
|
||||
extractFaces();
|
||||
}
|
||||
catch (Standard_Failure& e4) {
|
||||
Base::Console().Log("LOG - DVP::execute - extractFaces failed for %s - %s **\n",getNameInDocument(),e4.GetMessageString());
|
||||
}
|
||||
}
|
||||
#endif //#if MOD_TECHDRAW_HANDLE_FACES
|
||||
|
||||
addCosmeticVertexesToGeom();
|
||||
addCosmeticEdgesToGeom();
|
||||
addCenterLinesToGeom();
|
||||
}
|
||||
|
||||
GeometryObject* DrawViewPart::makeGeometryForShape(TopoDS_Shape shape)
|
||||
{
|
||||
// Base::Console().Message("DVP::makeGeometryforShape() - %s\n", Label.getValue());
|
||||
@@ -725,15 +748,10 @@ double DrawViewPart::getBoxY(void) const
|
||||
|
||||
QRectF DrawViewPart::getRect() const
|
||||
{
|
||||
// Base::Console().Message("DVP::getRect() - %s\n", getNameInDocument());
|
||||
double x = getBoxX();
|
||||
double y = getBoxY();
|
||||
QRectF result;
|
||||
if (std::isinf(x) || std::isinf(y)) {
|
||||
//geometry isn't created yet. return an arbitrary rect.
|
||||
result = QRectF(0.0,0.0,100.0,100.0);
|
||||
} else {
|
||||
result = QRectF(0.0,0.0,getBoxX(),getBoxY()); //this is from GO and is already scaled
|
||||
}
|
||||
QRectF result(0.0, 0.0, x, y);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -201,6 +201,7 @@ protected:
|
||||
|
||||
virtual TechDraw::GeometryObject* buildGeometryObject(TopoDS_Shape shape, gp_Ax2 viewAxis); //const??
|
||||
virtual TechDraw::GeometryObject* makeGeometryForShape(TopoDS_Shape shape); //const??
|
||||
void buildGeometry(TopoDS_Shape shape);
|
||||
|
||||
void extractFaces();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user