From 6cc849fb73ac677d4e0784268404784be245c6c1 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Wed, 30 Nov 2022 21:56:09 -0500 Subject: [PATCH] [TD]allow rotation of hatch directions - faces can have their svg and bitmap hatches rotated to match the view rotation or special situations - section cut face can have svg hatch rotated --- src/Mod/TechDraw/App/DrawGeomHatch.cpp | 57 ++++++- src/Mod/TechDraw/App/DrawGeomHatch.h | 15 +- src/Mod/TechDraw/App/DrawViewSection.cpp | 6 +- src/Mod/TechDraw/App/DrawViewSection.h | 2 + src/Mod/TechDraw/Gui/QGIFace.cpp | 91 ++++++---- src/Mod/TechDraw/Gui/QGIFace.h | 12 +- src/Mod/TechDraw/Gui/QGIViewPart.cpp | 13 +- src/Mod/TechDraw/Gui/QGIViewSection.cpp | 5 +- src/Mod/TechDraw/Gui/TaskGeomHatch.cpp | 31 ++++ src/Mod/TechDraw/Gui/TaskGeomHatch.h | 6 + src/Mod/TechDraw/Gui/TaskGeomHatch.ui | 159 ++++++++++++------ src/Mod/TechDraw/Gui/TaskHatch.cpp | 37 +++- src/Mod/TechDraw/Gui/TaskHatch.h | 6 + src/Mod/TechDraw/Gui/TaskHatch.ui | 102 ++++++++--- src/Mod/TechDraw/Gui/ViewProviderHatch.cpp | 8 +- src/Mod/TechDraw/Gui/ViewProviderHatch.h | 5 +- .../TechDraw/Gui/ViewProviderViewSection.cpp | 3 +- 17 files changed, 419 insertions(+), 139 deletions(-) diff --git a/src/Mod/TechDraw/App/DrawGeomHatch.cpp b/src/Mod/TechDraw/App/DrawGeomHatch.cpp index f0e2aafe57..2a6d33bcbd 100644 --- a/src/Mod/TechDraw/App/DrawGeomHatch.cpp +++ b/src/Mod/TechDraw/App/DrawGeomHatch.cpp @@ -86,6 +86,10 @@ DrawGeomHatch::DrawGeomHatch() ADD_PROPERTY_TYPE(ScalePattern, (1.0), vgroup, App::Prop_None, "GeomHatch pattern size adjustment"); ScalePattern.setConstraints(&scaleRange); + ADD_PROPERTY_TYPE(PatternRotation, (0.0), vgroup, App::Prop_None, + "Pattern rotation in degrees anticlockwise"); + ADD_PROPERTY_TYPE(PatternOffset, (0.0, 0.0, 0.0), vgroup, App::Prop_None, + "Pattern offset"); m_saveFile = ""; m_saveName = ""; @@ -242,14 +246,17 @@ std::vector DrawGeomHatch::getTrimmedLines(int i) //get the trimmed Base::Console().Log("DGH::getTrimmedLines - no source geometry\n"); return result; } - return getTrimmedLines(source, m_lineSets, i, ScalePattern.getValue()); + return getTrimmedLines(source, m_lineSets, i, ScalePattern.getValue(), + PatternRotation.getValue(), PatternOffset.getValue()); } /* static */ std::vector DrawGeomHatch::getTrimmedLinesSection(DrawViewSection* source, std::vector lineSets, TopoDS_Face f, - double scale ) + double scale, + double hatchRotation, + Base::Vector3d hatchOffset) { std::vector result; gp_Pln p; @@ -270,26 +277,35 @@ std::vector DrawGeomHatch::getTrimmedLinesSection(DrawViewSection* sou result = getTrimmedLines(source, lineSets, fMoved, - scale ); + scale, + hatchRotation, + hatchOffset ); return result; } //! get hatch lines trimmed to face outline -std::vector DrawGeomHatch::getTrimmedLines(DrawViewPart* source, std::vector lineSets, int iface, double scale ) +std::vector DrawGeomHatch::getTrimmedLines(DrawViewPart* source, std::vector lineSets, + int iface, double scale, double hatchRotation , + Base::Vector3d hatchOffset) { TopoDS_Face face = extractFace(source, iface); std::vector result = getTrimmedLines(source, lineSets, face, - scale ); + scale, + hatchRotation, + hatchOffset ); return result; } std::vector DrawGeomHatch::getTrimmedLines(DrawViewPart* source, std::vector lineSets, TopoDS_Face f, - double scale ) + double scale, + double hatchRotation, + Base::Vector3d hatchOffset) { +// Base::Console().Message("DGH::getTrimmedLines() - rotation: %.3f hatchOffset: %s\n", hatchRotation, DrawUtil::formatVector(hatchOffset).c_str()); (void)source; std::vector result; @@ -310,12 +326,26 @@ std::vector DrawGeomHatch::getTrimmedLines(DrawViewPart* source, //make Compound for this linespec BRep_Builder builder; - TopoDS_Compound grid; - builder.MakeCompound(grid); + TopoDS_Compound gridComp; + builder.MakeCompound(gridComp); for (auto& c: candidates) { - builder.Add(grid, c); + builder.Add(gridComp, c); } + TopoDS_Shape grid = gridComp; + if (hatchRotation != 0.0) { + double hatchRotationRad = hatchRotation * M_PI / 180.0; + gp_Ax1 gridAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Vec(gp::OZ().Direction())); + gp_Trsf xGridRotate; + xGridRotate.SetRotation(gridAxis, hatchRotationRad); + BRepBuilderAPI_Transform mkTransRotate(grid, xGridRotate, true); + grid = mkTransRotate.Shape(); + } + gp_Trsf xGridTranslate; + xGridTranslate.SetTranslation(DrawUtil::togp_Vec(hatchOffset)); + BRepBuilderAPI_Transform mkTransTranslate(grid, xGridTranslate, true); + grid = mkTransTranslate.Shape(); + //Common(Compound, Face) BRepAlgoAPI_Common mkCommon(face, grid); if ((!mkCommon.IsDone()) || @@ -369,6 +399,15 @@ std::vector DrawGeomHatch::makeEdgeOverlay(PATLineSpec hl, Bnd_Box double minX, maxX, minY, maxY, minZ, maxZ; b.Get(minX, minY, minZ, maxX, maxY, maxZ); + //make the overlay bigger to cover rotations. might need to be bigger than 2x. + double centerX = (minX + maxX) / 2.0; + double widthX = maxX - minX; + minX = centerX - widthX; + maxX = centerX + widthX; + double centerY = (minY + maxY) / 2.0; + double widthY = maxY - minY; + minY = centerY - widthY; + maxY = centerY + widthY; Base::Vector3d start; Base::Vector3d end; diff --git a/src/Mod/TechDraw/App/DrawGeomHatch.h b/src/Mod/TechDraw/App/DrawGeomHatch.h index 2398961dc4..04bf1b1cf7 100644 --- a/src/Mod/TechDraw/App/DrawGeomHatch.h +++ b/src/Mod/TechDraw/App/DrawGeomHatch.h @@ -61,6 +61,8 @@ public: App::PropertyFileIncluded PatIncluded; App::PropertyString NamePattern; App::PropertyFloatConstraint ScalePattern; + App::PropertyFloat PatternRotation; + App::PropertyVector PatternOffset; App::DocumentObjectExecReturn *execute(void) override; void onChanged(const App::Property* prop) override; @@ -77,17 +79,22 @@ public: std::vector getFaceOverlay(int i = 0); std::vector getTrimmedLines(int i = 0); - static std::vector getTrimmedLines(DrawViewPart* dvp, std::vector lineSets, int iface, double scale); + static std::vector getTrimmedLines(DrawViewPart* dvp, std::vector lineSets, int iface, + double scale, double hatchRotation = 0.0, + Base::Vector3d hatchOffset = Base::Vector3d(0.0, 0.0, 0.0)); static std::vector getTrimmedLines(DrawViewPart* source, std::vector lineSets, TopoDS_Face face, - double scale ); + double scale , double hatchRotation = 0.0, + Base::Vector3d hatchOffset = Base::Vector3d(0.0, 0.0, 0.0)); static std::vector getTrimmedLinesSection(DrawViewSection* source, std::vector lineSets, TopoDS_Face f, - double scale ); + double scale , double hatchRotation = 0.0, + Base::Vector3d hatchOffset = Base::Vector3d(0.0, 0.0, 0.0)); - static std::vector makeEdgeOverlay(PATLineSpec hl, Bnd_Box bBox, double scale); + static std::vector makeEdgeOverlay(PATLineSpec hl, Bnd_Box bBox, + double scale); static TopoDS_Edge makeLine(Base::Vector3d s, Base::Vector3d e); static std::vector getDecodedSpecsFromFile(std::string fileSpec, std::string myPattern); static TopoDS_Face extractFace(DrawViewPart* source, int iface ); diff --git a/src/Mod/TechDraw/App/DrawViewSection.cpp b/src/Mod/TechDraw/App/DrawViewSection.cpp index 8f481fc55a..b69c3a01a4 100644 --- a/src/Mod/TechDraw/App/DrawViewSection.cpp +++ b/src/Mod/TechDraw/App/DrawViewSection.cpp @@ -175,6 +175,8 @@ DrawViewSection::DrawViewSection() : "Embedded Pat pattern file. System use only."); // n/a to end users ADD_PROPERTY_TYPE(NameGeomPattern ,(DrawGeomHatch::prefGeomHatchName()), fgroup, App::Prop_None, "The pattern name for geometric hatching"); ADD_PROPERTY_TYPE(HatchScale, (1.0), fgroup, App::Prop_None, "Hatch pattern size adjustment"); + ADD_PROPERTY_TYPE(HatchRotation, (0.0), fgroup, App::Prop_None, "Rotation of hatch pattern in degrees anti-clockwise"); + ADD_PROPERTY_TYPE(HatchOffset, (0.0, 0.0, 0.0), fgroup, App::Prop_None, "Hatch pattern offset"); getParameters(); @@ -980,7 +982,9 @@ std::vector DrawViewSection::getDrawableLines(int i) std::vector result; result = DrawGeomHatch::getTrimmedLinesSection(this, m_lineSets, getSectionTopoDSFace(i), - HatchScale.getValue()); + HatchScale.getValue(), + HatchRotation.getValue(), + HatchOffset.getValue()); return result; } diff --git a/src/Mod/TechDraw/App/DrawViewSection.h b/src/Mod/TechDraw/App/DrawViewSection.h index 93877ef8eb..14d4545fb7 100644 --- a/src/Mod/TechDraw/App/DrawViewSection.h +++ b/src/Mod/TechDraw/App/DrawViewSection.h @@ -102,6 +102,8 @@ public: App::PropertyFileIncluded PatIncluded; App::PropertyString NameGeomPattern; App::PropertyFloat HatchScale; + App::PropertyFloat HatchRotation; + App::PropertyVector HatchOffset; App::PropertyBool FuseBeforeCut; App::PropertyBool TrimAfterCut; //new v021 diff --git a/src/Mod/TechDraw/Gui/QGIFace.cpp b/src/Mod/TechDraw/Gui/QGIFace.cpp index 45286624aa..0208aaafc5 100644 --- a/src/Mod/TechDraw/Gui/QGIFace.cpp +++ b/src/Mod/TechDraw/Gui/QGIFace.cpp @@ -68,7 +68,8 @@ using namespace TechDraw; QGIFace::QGIFace(int index) : projIndex(index), - m_hideSvgTiles(false) + m_hideSvgTiles(false), + m_hatchRotation(0.0) { m_segCount = 0; // setFillMode(NoFill); @@ -257,16 +258,17 @@ void QGIFace::lineSetToFillItems(LineSet& ls) { m_segCount = 0; QPen pen = setGeomPen(); - for (auto& g: ls.getGeoms()) { + for (auto& geom : ls.getGeoms()) { + //geom is a tdGeometry representation of 1 line in the pattern if (ls.isDashed()) { double offset = 0.0; - Base::Vector3d pStart = ls.getPatternStartPoint(g, offset, m_fillScale); + Base::Vector3d pStart = ls.getPatternStartPoint(geom, offset, m_fillScale); offset = Rez::guiX(offset); - Base::Vector3d gStart(g->getStartPoint().x, - g->getStartPoint().y, + Base::Vector3d gStart(geom->getStartPoint().x, + geom->getStartPoint().y, 0.0); - Base::Vector3d gEnd(g->getEndPoint().x, - g->getEndPoint().y, + Base::Vector3d gEnd(geom->getEndPoint().x, + geom->getEndPoint().y, 0.0); if (DrawUtil::fpCompare(offset, 0.0, 0.00001)) { //no offset QGraphicsPathItem* item1 = lineFromPoints(pStart, gEnd, ls.getDashSpec()); @@ -279,12 +281,12 @@ void QGIFace::lineSetToFillItems(LineSet& ls) } } else { //offset - pattern start not in g double remain = dashRemain(decodeDashSpec(ls.getDashSpec()), offset); - QGraphicsPathItem* shortItem = geomToStubbyLine(g, remain, ls); + QGraphicsPathItem* shortItem = geomToStubbyLine(geom, remain, ls); shortItem->setPen(pen); m_fillItems.push_back(shortItem); } } else { //not dashed - QGraphicsPathItem* fillItem = geomToLine(g, ls); + QGraphicsPathItem* fillItem = geomToLine(geom, ls); fillItem->setPen(pen); m_fillItems.push_back(fillItem); } @@ -520,19 +522,20 @@ void QGIFace::makeMark(double x, double y) void QGIFace::buildSvgHatch() { +// Base::Console().Message("QGIF::buildSvgHatch() - offset: %s\n", DrawUtil::formatVector(getHatchOffset()).c_str()); double wTile = SVGSIZEW * m_fillScale; double hTile = SVGSIZEH * m_fillScale; double w = m_outline.boundingRect().width(); double h = m_outline.boundingRect().height(); - QRectF r = m_outline.boundingRect(); - QPointF fCenter = r.center(); - double nw = ceil(w / wTile); - double nh = ceil(h / hTile); + //make the hatch tiled area big enough to handle rotations + double hatchOverlaySize = 2.0 * std::max(w, h); + QPointF faceCenter = m_outline.boundingRect().center(); + double nw = ceil(hatchOverlaySize / wTile); + double nh = ceil(hatchOverlaySize / hTile); w = nw * wTile; h = nh * hTile; m_rect->setRect(0., 0., w,-h); - m_rect->centerAt(fCenter); - r = m_rect->rect(); + m_rect->centerAt(faceCenter); QByteArray before, after; before = QString::fromStdString(SVGCOLPREFIX + SVGCOLDEFAULT).toUtf8(); after = QString::fromStdString(SVGCOLPREFIX + m_svgCol).toUtf8(); @@ -544,7 +547,8 @@ void QGIFace::buildSvgHatch() tile->setScale(m_fillScale); if (tile->load(&colorXML)) { tile->setParentItem(m_rect); - tile->setPos(iw*wTile, -h + ih*hTile); + tile->setPos(iw*wTile + getHatchOffset().x, + -h + ih*hTile + getHatchOffset().y); } tileCount++; if (tileCount > m_maxTile) { @@ -556,6 +560,9 @@ void QGIFace::buildSvgHatch() break; } } + QPointF faceCenterToMRect = mapToItem(m_rect, faceCenter); + m_rect->setTransformOriginPoint(faceCenterToMRect); + m_rect->setRotation(m_hatchRotation); } void QGIFace::clearSvg() @@ -565,21 +572,22 @@ void QGIFace::clearSvg() void QGIFace::buildPixHatch() { +// Base::Console().Message("QGIF::buildPixHatch() - offset: %s\n", DrawUtil::formatVector(getHatchOffset()).c_str()); double wTile = SVGSIZEW * m_fillScale; double hTile = SVGSIZEH * m_fillScale; - double w = m_outline.boundingRect().width(); - double h = m_outline.boundingRect().height(); - QRectF r = m_outline.boundingRect(); - QPointF fCenter = r.center(); - double nw = ceil(w / wTile); - double nh = ceil(h / hTile); - w = nw * wTile; - h = nh * hTile; + double faceWidth = m_outline.boundingRect().width(); + double faceHeight = m_outline.boundingRect().height(); + QRectF faceRect = m_outline.boundingRect(); + QPointF faceCenter = faceRect.center(); + double hatchOverlaySize = 2.0 * std::max(faceWidth, faceHeight); + double numberWide = ceil(hatchOverlaySize / wTile); + double numberHigh = ceil(hatchOverlaySize / hTile); + double overlayWidth = numberWide * wTile; + double overlayHeight= numberHigh * hTile; - m_rect->setRect(0., 0., w,-h); - m_rect->centerAt(fCenter); + m_rect->setRect(0., 0., overlayWidth, -overlayHeight); + m_rect->centerAt(faceCenter); - r = m_rect->rect(); QByteArray before, after; before = QString::fromStdString(SVGCOLPREFIX + SVGCOLDEFAULT).toUtf8(); after = QString::fromStdString(SVGCOLPREFIX + m_svgCol).toUtf8(); @@ -590,16 +598,16 @@ void QGIFace::buildPixHatch() Base::Console().Error("QGIF::buildPixHatch - renderer failed to load\n"); } + //get the svg tile graphics as a QImage QImage imageIn(64, 64, QImage::Format_ARGB32); imageIn.fill(Qt::transparent); QPainter painter(&imageIn); - renderer.render(&painter); if (imageIn.isNull()) { Base::Console().Error("QGIF::buildPixHatch - imageIn is null\n"); return; } - + //make a QPixmap tile of the QImage QPixmap pm(64, 64); pm = QPixmap::fromImage(imageIn); pm = pm.scaled(wTile, hTile); @@ -608,23 +616,26 @@ void QGIFace::buildPixHatch() return; } - QImage tileField(w, h, QImage::Format_ARGB32); - QPointF fieldCenter(w / 2.0, h / 2.0); + //layout a field of QPixmap tiles as a QImage + QImage tileField(overlayWidth, overlayHeight, QImage::Format_ARGB32); + QPointF fieldCenter(overlayWidth, overlayHeight); + //do we have to rotate the field before we clip it?? tileField.fill(Qt::transparent); QPainter painter2(&tileField); QPainter::RenderHints hints = painter2.renderHints(); hints = hints & QPainter::Antialiasing; painter2.setRenderHints(hints); QPainterPath clipper = path(); - QPointF offset = (fieldCenter - fCenter); + QPointF offset = (fieldCenter - faceCenter); clipper.translate(offset); painter2.setClipPath(clipper); long int tileCount = 0; - for (int iw = 0; iw < int(nw); iw++) { - for (int ih = 0; ih < int(nh); ih++) { - painter2.drawPixmap(QRectF(iw*wTile, ih*hTile, wTile, hTile), //target rect + for (int iw = 0; iw < int(numberWide); iw++) { + for (int ih = 0; ih < int(numberHigh); ih++) { + painter2.drawPixmap(QRectF(iw*wTile + getHatchOffset().x, ih*hTile + getHatchOffset().y, + wTile, hTile), //target rect pm, //map QRectF(0, 0, wTile, hTile)); //source rect tileCount++; @@ -637,13 +648,14 @@ void QGIFace::buildPixHatch() break; } } - QPixmap bigMap(fabs(r.width()), fabs(r.height())); + + QPixmap bigMap(fabs(faceRect.width()), fabs(faceRect.height())); bigMap = QPixmap::fromImage(tileField); QPixmap nothing; m_image->setPixmap(nothing); m_image->load(bigMap); - m_image->centerAt(fCenter); + m_image->centerAt(faceCenter); } //this isn't used currently @@ -692,6 +704,11 @@ QPixmap QGIFace::textureFromBitmap(std::string fileSpec) } QByteArray bytes = f.readAll(); pix.loadFromData(bytes); + if (m_hatchRotation != 0.0) { + QTransform rotator; + rotator.rotate(m_hatchRotation); + pix = pix.transformed(rotator); + } return pix; } diff --git a/src/Mod/TechDraw/Gui/QGIFace.h b/src/Mod/TechDraw/Gui/QGIFace.h index dc0000d160..d26e55a1e7 100644 --- a/src/Mod/TechDraw/Gui/QGIFace.h +++ b/src/Mod/TechDraw/Gui/QGIFace.h @@ -113,6 +113,13 @@ public: QPixmap textureFromBitmap(std::string fileSpec); QPixmap textureFromSvg(std::string fillSpec); + //Qt uses clockwise degrees + void setHatchRotation(double degrees) { m_hatchRotation = -degrees; } + double getHatchRotation() const { return -m_hatchRotation; } + + void setHatchOffset(Base::Vector3d offset) { m_hatchOffset = offset; } + Base::Vector3d getHatchOffset() { return m_hatchOffset; } + protected: void makeMark(double x, double y); double getXForm(); @@ -146,7 +153,6 @@ protected: bool m_hideSvgTiles; - private: QPixmap m_texture; // @@ -158,6 +164,10 @@ private: double m_geomWeight; //lineweight for crosshatch lines bool m_defClearFace; QColor m_defFaceColor; + + double m_hatchRotation; + Base::Vector3d m_hatchOffset; + }; } diff --git a/src/Mod/TechDraw/Gui/QGIViewPart.cpp b/src/Mod/TechDraw/Gui/QGIViewPart.cpp index 7691e158f2..dfbabfe08f 100644 --- a/src/Mod/TechDraw/Gui/QGIViewPart.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewPart.cpp @@ -485,6 +485,8 @@ void QGIViewPart::drawViewPart() if (hatchScale > 0.0) { newFace->setHatchScale(fGeom->ScalePattern.getValue()); } + newFace->setHatchRotation(fGeom->PatternRotation.getValue()); + newFace->setHatchOffset(fGeom->PatternOffset.getValue()); newFace->setHatchFile(fGeom->PatIncluded.getValue()); Gui::ViewProvider* gvp = QGIView::getViewProvider(fGeom); ViewProviderGeomHatch* geomVp = dynamic_cast(gvp); @@ -495,6 +497,8 @@ void QGIViewPart::drawViewPart() } } } else if (fHatch) { + Gui::ViewProvider* gvp = QGIView::getViewProvider(fHatch); + ViewProviderHatch* hatchVp = dynamic_cast(gvp); if (fHatch->isSvgHatch()) { if (!fHatch->SvgIncluded.isEmpty()) { if (getExporting()) { @@ -505,20 +509,25 @@ void QGIViewPart::drawViewPart() newFace->isHatched(true); newFace->setFillMode(QGIFace::SvgFill); newFace->setHatchFile(fHatch->SvgIncluded.getValue()); - Gui::ViewProvider* gvp = QGIView::getViewProvider(fHatch); - ViewProviderHatch* hatchVp = dynamic_cast(gvp); +// Gui::ViewProvider* gvp = QGIView::getViewProvider(fHatch); +// ViewProviderHatch* hatchVp = dynamic_cast(gvp); if (hatchVp) { double hatchScale = hatchVp->HatchScale.getValue(); if (hatchScale > 0.0) { newFace->setHatchScale(hatchVp->HatchScale.getValue()); } newFace->setHatchColor(hatchVp->HatchColor.getValue()); + newFace->setHatchRotation(hatchVp->HatchRotation.getValue()); + newFace->setHatchOffset(hatchVp->HatchOffset.getValue()); } } } else { //bitmap hatch newFace->isHatched(true); newFace->setFillMode(QGIFace::BitmapFill); newFace->setHatchFile(fHatch->SvgIncluded.getValue()); + if (hatchVp) { + newFace->setHatchRotation(hatchVp->HatchRotation.getValue()); + } } } bool drawEdges = prefFaceEdges(); diff --git a/src/Mod/TechDraw/Gui/QGIViewSection.cpp b/src/Mod/TechDraw/Gui/QGIViewSection.cpp index 3aad751c52..68b1600829 100644 --- a/src/Mod/TechDraw/Gui/QGIViewSection.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewSection.cpp @@ -117,7 +117,8 @@ void QGIViewSection::drawSectionFace() newFace->setFillMode(QGIFace::SvgFill); newFace->setHatchColor(sectionVp->HatchColor.getValue()); newFace->setHatchScale(section->HatchScale.getValue()); -// std::string hatchSpec = section->FileHatchPattern.getValue(); + newFace->setHatchRotation(section->HatchRotation.getValue()); + newFace->setHatchOffset(section->HatchOffset.getValue()); std::string hatchSpec = section->SvgIncluded.getValue(); newFace->setHatchFile(hatchSpec); } else if (section->CutSurfaceDisplay.isValue("PatHatch")) { @@ -126,6 +127,8 @@ void QGIViewSection::drawSectionFace() newFace->setHatchColor(sectionVp->GeomHatchColor.getValue()); newFace->setHatchScale(section->HatchScale.getValue()); newFace->setLineWeight(sectionVp->WeightPattern.getValue()); + newFace->setHatchRotation(section->HatchRotation.getValue()); + newFace->setHatchOffset(section->HatchOffset.getValue()); std::vector lineSets = section->getDrawableLines(i); if (!lineSets.empty()) { newFace->clearLineSets(); diff --git a/src/Mod/TechDraw/Gui/TaskGeomHatch.cpp b/src/Mod/TechDraw/Gui/TaskGeomHatch.cpp index ff2047c8df..c9686611ba 100644 --- a/src/Mod/TechDraw/Gui/TaskGeomHatch.cpp +++ b/src/Mod/TechDraw/Gui/TaskGeomHatch.cpp @@ -90,6 +90,13 @@ void TaskGeomHatch::initUi() connect(ui->sbWeight, SIGNAL(valueChanged(double)), this, SLOT(onLineWeightChanged())); ui->ccColor->setColor(m_color.asValue()); connect(ui->ccColor, SIGNAL(changed()), this, SLOT(onColorChanged())); + + ui->dsbRotation->setValue(m_rotation); + connect(ui->dsbRotation, SIGNAL(valueChanged(double)), this, SLOT(onRotationChanged())); + ui->dsbOffsetX->setValue(m_offset.x); + connect(ui->dsbOffsetX, SIGNAL(valueChanged(double)), this, SLOT(onOffsetChanged())); + ui->dsbOffsetY->setValue(m_offset.y); + connect(ui->dsbOffsetY, SIGNAL(valueChanged(double)), this, SLOT(onOffsetChanged())); } void TaskGeomHatch::onFileChanged() @@ -119,6 +126,23 @@ void TaskGeomHatch::onScaleChanged() dv->requestPaint(); } +void TaskGeomHatch::onRotationChanged() +{ + m_rotation = ui->dsbRotation->value(); + m_hatch->PatternRotation.setValue(m_rotation); + TechDraw::DrawView* dv = static_cast(m_source); + dv->requestPaint(); +} + +void TaskGeomHatch::onOffsetChanged() +{ + Base::Vector3d offset(ui->dsbOffsetX->value(), ui->dsbOffsetY->value(), 0.0); + m_offset = offset; + m_hatch->PatternOffset.setValue(m_offset); + TechDraw::DrawView* dv = static_cast(m_source); + dv->requestPaint(); +} + void TaskGeomHatch::onLineWeightChanged() { m_weight =ui->sbWeight->value().getValue(); @@ -156,6 +180,8 @@ bool TaskGeomHatch::reject() m_hatch->FilePattern.setValue(m_origFile); m_hatch->NamePattern.setValue(m_origName); m_hatch->ScalePattern.setValue(m_origScale); + m_hatch->PatternRotation.setValue(m_origRotation); + m_hatch->PatternOffset.setValue(m_origOffset); m_Vp->ColorPattern.setValue(m_origColor); m_Vp->WeightPattern.setValue(m_origWeight); } @@ -167,6 +193,8 @@ void TaskGeomHatch::getParameters() m_file = m_hatch->FilePattern.getValue(); m_name = m_hatch->NamePattern.getValue(); m_scale = m_hatch->ScalePattern.getValue(); + m_rotation = m_hatch->PatternRotation.getValue(); + m_offset = m_hatch->PatternOffset.getValue(); m_color = m_Vp->ColorPattern.getValue(); m_weight = m_Vp->WeightPattern.getValue(); if (!getCreateMode()) { @@ -175,6 +203,8 @@ void TaskGeomHatch::getParameters() m_origScale = m_hatch->ScalePattern.getValue(); m_origColor = m_Vp->ColorPattern.getValue(); m_origWeight = m_Vp->WeightPattern.getValue(); + m_origRotation = m_hatch->PatternRotation.getValue(); + m_origOffset = m_hatch->PatternOffset.getValue(); } } @@ -193,6 +223,7 @@ void TaskGeomHatch::updateValues() m_Vp->ColorPattern.setValue(m_color); m_weight = ui->sbWeight->value().getValue(); m_Vp->WeightPattern.setValue(m_weight); + m_hatch->PatternRotation.setValue(ui->dsbRotation->value()); } QStringList TaskGeomHatch::listToQ(std::vector inList) diff --git a/src/Mod/TechDraw/Gui/TaskGeomHatch.h b/src/Mod/TechDraw/Gui/TaskGeomHatch.h index 10f1725cc9..d2d9742489 100644 --- a/src/Mod/TechDraw/Gui/TaskGeomHatch.h +++ b/src/Mod/TechDraw/Gui/TaskGeomHatch.h @@ -83,6 +83,10 @@ private: double m_origScale; double m_origWeight; App::Color m_origColor; + double m_rotation; + double m_origRotation; + Base::Vector3d m_offset; + Base::Vector3d m_origOffset; bool m_createMode; @@ -91,6 +95,8 @@ private Q_SLOTS: void onScaleChanged(); void onLineWeightChanged(); void onColorChanged(); + void onRotationChanged(); + void onOffsetChanged(); }; diff --git a/src/Mod/TechDraw/Gui/TaskGeomHatch.ui b/src/Mod/TechDraw/Gui/TaskGeomHatch.ui index 009d229f53..cbe79e343b 100644 --- a/src/Mod/TechDraw/Gui/TaskGeomHatch.ui +++ b/src/Mod/TechDraw/Gui/TaskGeomHatch.ui @@ -7,7 +7,7 @@ 0 0 385 - 191 + 314 @@ -47,7 +47,7 @@ - + @@ -60,10 +60,37 @@ - + + + + + Pattern Scale + + + + + + + Rotation + + + + + + + + 0 + 22 + + + + Color of pattern lines + + + @@ -71,18 +98,12 @@ - - - - Qt::Horizontal + + + + Offset X - - - 40 - 20 - - - + @@ -97,41 +118,6 @@ - - - - Pattern Scale - - - - - - - - 0 - 22 - - - - Enlarges/shrinks the pattern - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - false - - - 0.100000000000000 - - - 0.100000000000000 - - - 1.000000000000000 - - - @@ -139,6 +125,22 @@ + + + + true + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + -360.000000000000000 + + + 360.000000000000000 + + + @@ -167,15 +169,28 @@ - + + + + Qt::Horizontal + + + + 40 + 20 + + + + + Line Color - - + + 0 @@ -183,11 +198,47 @@ - Color of pattern lines + Enlarges/shrinks the pattern + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + 0.100000000000000 + + + 0.100000000000000 + + + 1.000000000000000 - + + + + Offset Y + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + diff --git a/src/Mod/TechDraw/Gui/TaskHatch.cpp b/src/Mod/TechDraw/Gui/TaskHatch.cpp index 92dea1314e..68fdeb7fed 100644 --- a/src/Mod/TechDraw/Gui/TaskHatch.cpp +++ b/src/Mod/TechDraw/Gui/TaskHatch.cpp @@ -68,7 +68,9 @@ TaskHatch::TaskHatch(TechDraw::DrawViewPart* inDvp, std::vector sub connect(ui->fcFile, SIGNAL(fileNameSelected(QString)), this, SLOT(onFileChanged())); connect(ui->sbScale, SIGNAL(valueChanged(double)), this, SLOT(onScaleChanged())); connect(ui->ccColor, SIGNAL(changed()), this, SLOT(onColorChanged())); - + connect(ui->dsbRotation, SIGNAL(valueChanged(double)), this, SLOT(onRotationChanged())); + connect(ui->dsbOffsetX, SIGNAL(valueChanged(double)), this, SLOT(onOffsetChanged())); + connect(ui->dsbOffsetY, SIGNAL(valueChanged(double)), this, SLOT(onOffsetChanged())); setUiPrimary(); } @@ -86,6 +88,9 @@ TaskHatch::TaskHatch(TechDrawGui::ViewProviderHatch* inVp) : connect(ui->fcFile, SIGNAL(fileNameSelected(QString)), this, SLOT(onFileChanged())); connect(ui->sbScale, SIGNAL(valueChanged(double)), this, SLOT(onScaleChanged())); connect(ui->ccColor, SIGNAL(changed()), this, SLOT(onColorChanged())); + connect(ui->dsbRotation, SIGNAL(valueChanged(double)), this, SLOT(onRotationChanged())); + connect(ui->dsbOffsetX, SIGNAL(valueChanged(double)), this, SLOT(onOffsetChanged())); + connect(ui->dsbOffsetY, SIGNAL(valueChanged(double)), this, SLOT(onOffsetChanged())); saveHatchState(); setUiEdit(); @@ -103,6 +108,7 @@ void TaskHatch::setUiPrimary() ui->sbScale->setValue(1.0); ui->sbScale->setSingleStep(0.1); ui->ccColor->setColor(TechDraw::DrawHatch::prefSvgHatchColor().asValue()); + ui->dsbRotation->setValue(0.0); } void TaskHatch::setUiEdit() @@ -114,6 +120,9 @@ void TaskHatch::setUiEdit() ui->sbScale->setValue(m_saveScale); ui->sbScale->setSingleStep(0.1); ui->ccColor->setColor(m_saveColor.asValue()); + ui->dsbRotation->setValue(m_saveRotation); + ui->dsbOffsetX->setValue(m_saveOffset.x); + ui->dsbOffsetY->setValue(m_saveOffset.y); } void TaskHatch::saveHatchState() @@ -121,6 +130,9 @@ void TaskHatch::saveHatchState() m_saveFile = m_hatch->HatchPattern.getValue(); m_saveScale = m_vp->HatchScale.getValue(); m_saveColor = m_vp->HatchColor.getValue(); + m_saveRotation = m_vp->HatchRotation.getValue(); + m_saveOffset = m_vp->HatchOffset.getValue(); + } //restore the start conditions @@ -131,6 +143,8 @@ void TaskHatch::restoreHatchState() m_hatch->HatchPattern.setValue(m_saveFile); m_vp->HatchScale.setValue(m_saveScale); m_vp->HatchColor.setValue(m_saveColor); + m_vp->HatchRotation.setValue(m_saveRotation); + m_vp->HatchOffset.setValue(m_saveOffset); } } @@ -152,6 +166,19 @@ void TaskHatch::onColorChanged() apply(); } +void TaskHatch::onRotationChanged() +{ + m_rotation = ui->dsbRotation->value(); + apply(); +} + +void TaskHatch::onOffsetChanged() +{ + m_offset.x = ui->dsbOffsetX->value(); + m_offset.y = ui->dsbOffsetY->value(); + apply(); +} + void TaskHatch::apply(bool forceUpdate) { Q_UNUSED(forceUpdate) @@ -173,7 +200,7 @@ void TaskHatch::apply(bool forceUpdate) void TaskHatch::createHatch() { - Base::Console().Message("TH::createHatch()\n"); +// Base::Console().Message("TH::createHatch()\n"); App::Document* doc = m_dvp->getDocument(); std::string FeatName = doc->getUniqueObjectName("Hatch"); std::stringstream featLabel; @@ -200,6 +227,9 @@ void TaskHatch::createHatch() ac.setValue(ui->ccColor->color()); m_vp->HatchColor.setValue(ac); m_vp->HatchScale.setValue(ui->sbScale->value().getValue()); + m_vp->HatchRotation.setValue(ui->dsbRotation->value()); + Base::Vector3d offset(ui->dsbOffsetX->value(), ui->dsbOffsetY->value(), 0.0); + m_vp->HatchOffset.setValue(offset); } else { Base::Console().Error("TaskHatch - Hatch has no ViewProvider\n"); } @@ -221,6 +251,9 @@ void TaskHatch::updateHatch() ac.setValue(ui->ccColor->color()); m_vp->HatchColor.setValue(ac); m_vp->HatchScale.setValue(ui->sbScale->value().getValue()); + m_vp->HatchRotation.setValue(ui->dsbRotation->value()); + Base::Vector3d offset(ui->dsbOffsetX->value(), ui->dsbOffsetY->value(), 0.0); + m_vp->HatchOffset.setValue(offset); Command::commitCommand(); } diff --git a/src/Mod/TechDraw/Gui/TaskHatch.h b/src/Mod/TechDraw/Gui/TaskHatch.h index 3215307f96..d5c234f3a8 100644 --- a/src/Mod/TechDraw/Gui/TaskHatch.h +++ b/src/Mod/TechDraw/Gui/TaskHatch.h @@ -61,6 +61,8 @@ protected Q_SLOTS: void onFileChanged(); void onScaleChanged(); void onColorChanged(); + void onRotationChanged(); + void onOffsetChanged(); protected: void changeEvent(QEvent *e) override; @@ -85,11 +87,15 @@ private: std::string m_file; double m_scale; App::Color m_color; + double m_rotation; + Base::Vector3d m_offset; std::string m_saveFile; double m_saveScale; App::Color m_saveColor; std::vector m_saveSubs; + double m_saveRotation; + Base::Vector3d m_saveOffset; }; diff --git a/src/Mod/TechDraw/Gui/TaskHatch.ui b/src/Mod/TechDraw/Gui/TaskHatch.ui index 97b7d39d44..53148f1f0f 100644 --- a/src/Mod/TechDraw/Gui/TaskHatch.ui +++ b/src/Mod/TechDraw/Gui/TaskHatch.ui @@ -7,7 +7,7 @@ 0 0 398 - 148 + 244 @@ -66,26 +66,7 @@ - - - - - - 0 - 0 - - - - - 0 - 26 - - - - Color of pattern lines (Svg Only) - - - + @@ -120,6 +101,58 @@ + + + + Svg Line Color + + + + + + + Offset X + + + + + + + + 0 + 0 + + + + + 0 + 26 + + + + Color of pattern lines (Svg Only) + + + + + + + Rotation the pattern (degrees) + + + true + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + -360.000000000000000 + + + 360.000000000000000 + + + @@ -127,10 +160,31 @@ - - + + - Svg Line Color + Rotation + + + + + + + Offset Y + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter diff --git a/src/Mod/TechDraw/Gui/ViewProviderHatch.cpp b/src/Mod/TechDraw/Gui/ViewProviderHatch.cpp index dc44317dcf..cce1744ad8 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderHatch.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderHatch.cpp @@ -65,6 +65,8 @@ ViewProviderHatch::ViewProviderHatch() vgroup, App::Prop_None, "The color of the hatch pattern"); ADD_PROPERTY_TYPE(HatchScale, (1.0), vgroup, App::Prop_None, "Hatch pattern size adjustment"); HatchScale.setConstraints(&scaleRange); + ADD_PROPERTY_TYPE(HatchRotation, (0.0), vgroup, App::Prop_None, "Hatch pattern rotation"); + ADD_PROPERTY_TYPE(HatchOffset, (0.0, 0.0, 0.0), vgroup, App::Prop_None, "Hatch pattern offset"); } ViewProviderHatch::~ViewProviderHatch() @@ -94,8 +96,10 @@ bool ViewProviderHatch::doubleClicked() void ViewProviderHatch::onChanged(const App::Property* prop) { - if ((prop == &HatchScale) || - (prop == &HatchColor)) { + if (prop == &HatchScale || + prop == &HatchColor || + prop == &HatchRotation || + prop == &HatchOffset) { if (HatchScale.getValue() > 0.0) { TechDraw::DrawViewPart* parent = getViewObject()->getSourceView(); if (parent) { diff --git a/src/Mod/TechDraw/Gui/ViewProviderHatch.h b/src/Mod/TechDraw/Gui/ViewProviderHatch.h index 40815f05bf..6904616ac2 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderHatch.h +++ b/src/Mod/TechDraw/Gui/ViewProviderHatch.h @@ -26,6 +26,7 @@ #define DRAWINGGUI_VIEWPROVIDERHATCH_H #include +#include #include @@ -46,8 +47,10 @@ public: /// destructor ~ViewProviderHatch() override; - App::PropertyColor HatchColor; + App::PropertyColor HatchColor; App::PropertyFloatConstraint HatchScale; + App::PropertyFloat HatchRotation; + App::PropertyVector HatchOffset; bool useNewSelectionModel() const override {return false;} void onChanged(const App::Property* prop) override; diff --git a/src/Mod/TechDraw/Gui/ViewProviderViewSection.cpp b/src/Mod/TechDraw/Gui/ViewProviderViewSection.cpp index 0f9d3b0fed..976cb4365d 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderViewSection.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderViewSection.cpp @@ -99,7 +99,8 @@ void ViewProviderViewSection::updateData(const App::Property* prop) if (prop == &(getViewObject()->FileHatchPattern) || prop == &(getViewObject()->CutSurfaceDisplay) || prop == &(getViewObject()->NameGeomPattern) || - prop == &(getViewObject()->HatchScale) ) { + prop == &(getViewObject()->HatchScale) || + prop == &(getViewObject()->HatchRotation) ) { updateGraphic(); }