Files
create/src/Gui/ViewProviderImagePlane.cpp
Kacper Donat 651cefde4d Gui: Use getObject<T>() helpers in classes
This commit is generated using regex based find and replace:

```
s/[\w:]+_cast\s*<([^>]+)\*>\s*\(\s*getObject\(\s*\)\)/getObject<$1>/
s/[\w:]+_cast\s*<([^>]+)\*>\s*\(\s*([^)]*)\s*->\s*getObject\(\s*\)\)/$2->getObject<$1>()/
```

To regenerate if needed.
2024-12-06 18:29:39 +01:00

345 lines
11 KiB
C++

/***************************************************************************
* Copyright (c) 2011 Jürgen Riegel (juergen.riegel@web.de) *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
# include <QAction>
# include <QFileInfo>
# include <QImage>
# include <QMenu>
# include <QString>
# include <QSvgRenderer>
# include <Inventor/nodes/SoCoordinate3.h>
# include <Inventor/nodes/SoFaceSet.h>
# include <Inventor/nodes/SoLightModel.h>
# include <Inventor/nodes/SoMaterial.h>
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoShapeHints.h>
# include <Inventor/nodes/SoTexture2.h>
# include <Inventor/nodes/SoTextureCoordinate2.h>
#endif
#include <App/Document.h>
#include <Gui/ActionFunction.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Control.h>
#include <Gui/TaskView/TaskImage.h>
#include <App/ImagePlane.h>
#include "ViewProviderImagePlane.h"
using namespace Gui;
PROPERTY_SOURCE(Gui::ViewProviderImagePlane, Gui::ViewProviderGeometryObject)
const char* ViewProviderImagePlane::LightingEnums[]= {"One side", "Two side", nullptr};
ViewProviderImagePlane::ViewProviderImagePlane()
{
ADD_PROPERTY_TYPE(Lighting,(1L), "Object Style", App::Prop_None, "Set object lighting.");
Lighting.setEnums(LightingEnums);
texture = new SoTexture2;
texture->ref();
pcCoords = new SoCoordinate3();
pcCoords->ref();
shapeHints = new SoShapeHints;
shapeHints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;
shapeHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
shapeHints->ref();
sPixmap = "image-plane";
ShapeAppearance.setDiffuseColor(1.0F, 1.0F, 1.0F);
}
ViewProviderImagePlane::~ViewProviderImagePlane()
{
pcCoords->unref();
texture->unref();
shapeHints->unref();
}
void ViewProviderImagePlane::attach(App::DocumentObject *pcObj)
{
ViewProviderGeometryObject::attach(pcObj);
// NOTE: SoFCSelection node has beem removed because it led to
// problems using the image as a construction plane with the
// draft commands
SoSeparator* shading = new SoSeparator;
shading->addChild(pcCoords);
SoTextureCoordinate2 *textCoord = new SoTextureCoordinate2;
textCoord->point.set1Value(0,0,0);
textCoord->point.set1Value(1,1,0);
textCoord->point.set1Value(2,1,1);
textCoord->point.set1Value(3,0,1);
shading->addChild(textCoord);
// texture
texture->model = SoTexture2::MODULATE;
shading->addChild(texture);
shading->addChild(shapeHints);
shading->addChild(pcShapeMaterial);
// plane
pcCoords->point.set1Value(0,0,0,0);
pcCoords->point.set1Value(1,1,0,0);
pcCoords->point.set1Value(2,1,1,0);
pcCoords->point.set1Value(3,0,1,0);
SoFaceSet *faceset = new SoFaceSet;
faceset->numVertices.set1Value(0,4);
shading->addChild(faceset);
addDisplayMaskMode(shading, "Shading");
SoLightModel* lightmodel = new SoLightModel;
lightmodel->model = SoLightModel::BASE_COLOR;
SoSeparator* noshading = new SoSeparator;
noshading->addChild(pcCoords);
noshading->addChild(textCoord);
noshading->addChild(texture);
noshading->addChild(shapeHints);
noshading->addChild(pcShapeMaterial);
noshading->addChild(lightmodel);
noshading->addChild(faceset);
addDisplayMaskMode(noshading, "No shading");
}
void ViewProviderImagePlane::setDisplayMode(const char* ModeName)
{
if (strcmp("Shading", ModeName) == 0) {
setDisplayMaskMode("Shading");
}
else if (strcmp("No shading", ModeName) == 0) {
setDisplayMaskMode("No shading");
}
ViewProviderGeometryObject::setDisplayMode(ModeName);
}
std::vector<std::string> ViewProviderImagePlane::getDisplayModes() const
{
std::vector<std::string> StrList;
StrList.emplace_back("Shading");
StrList.emplace_back("No shading");
return StrList;
}
void ViewProviderImagePlane::onChanged(const App::Property* prop)
{
if (prop == &Lighting) {
if (Lighting.getValue() == 0)
shapeHints->vertexOrdering = SoShapeHints::UNKNOWN_ORDERING;
else
shapeHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
}
ViewProviderGeometryObject::onChanged(prop);
}
void ViewProviderImagePlane::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
{
Gui::ActionFunction* func = new Gui::ActionFunction(menu);
QAction* action = menu->addAction(QObject::tr("Change image..."));
action->setIcon(QIcon(QLatin1String("images:image-scaling.svg")));
func->trigger(action, [this](){
this->manipulateImage();
});
ViewProviderGeometryObject::setupContextMenu(menu, receiver, member);
}
bool ViewProviderImagePlane::doubleClicked()
{
manipulateImage();
return true;
}
void ViewProviderImagePlane::manipulateImage()
{
auto dialog = new TaskImageDialog(getObject<Image::ImagePlane>());
Gui::Control().showDialog(dialog);
}
void ViewProviderImagePlane::resizePlane(float xsize, float ysize)
{
pcCoords->point.set1Value(0,-(xsize/2),-(ysize/2),0.0);
pcCoords->point.set1Value(1,+(xsize/2),-(ysize/2),0.0);
pcCoords->point.set1Value(2,+(xsize/2),+(ysize/2),0.0);
pcCoords->point.set1Value(3,-(xsize/2),+(ysize/2),0.0);
}
void ViewProviderImagePlane::loadImage()
{
Image::ImagePlane* imagePlane = static_cast<Image::ImagePlane*>(pcObject);
std::string fileName = imagePlane->ImageFile.getValue();
if (!fileName.empty()) {
QImage impQ;
if (isSvgFile(fileName.c_str())) {
impQ = loadSvg(fileName.c_str());
}
else {
impQ = loadRaster(fileName.c_str());
}
QSizeF size = getSizeInMM(impQ);
setPlaneSize(size, impQ);
convertToSFImage(impQ);
}
}
void ViewProviderImagePlane::setPlaneSize(const QSizeF& size, const QImage& img)
{
if (!img.isNull()) {
Image::ImagePlane* imagePlane = static_cast<Image::ImagePlane*>(pcObject);
// When restoring the document or importing a ImagePlane by eg. pasting it
// preserve the X and Y size.
if (!isRestoring() && !pcObject->testStatus(App::ObjectStatus::ObjImporting)) {
imagePlane->XSize.setValue(size.width());
imagePlane->YSize.setValue(size.height());
}
imagePlane->XPixelsPerMeter = img.dotsPerMeterX();
imagePlane->YPixelsPerMeter = img.dotsPerMeterY();
}
}
QImage ViewProviderImagePlane::loadRaster(const char* fileName) const
{
QImage img;
img.load(QString::fromUtf8(fileName));
return img;
}
void ViewProviderImagePlane::reloadIfSvg()
{
Image::ImagePlane* imagePlane = static_cast<Image::ImagePlane*>(pcObject);
std::string fileName = imagePlane->ImageFile.getValue();
if (isSvgFile(fileName.c_str())) {
double xsize = imagePlane->XSize.getValue();
double ysize = imagePlane->YSize.getValue();
QImage impQ = loadSvgOfSize(fileName.c_str(), QSizeF(xsize, ysize));
convertToSFImage(impQ);
}
}
QImage ViewProviderImagePlane::loadSvg(const char* filename) const
{
QSizeF defaultSize = defaultSizeOfSvg(filename);
QPixmap px = BitmapFactory().pixmapFromSvg(filename, defaultSize);
return px.toImage();
}
QImage ViewProviderImagePlane::loadSvgOfSize(const char* filename, const QSizeF& size) const
{
QSizeF psize = pixelSize(filename, size);
QPixmap px = BitmapFactory().pixmapFromSvg(filename, psize);
return px.toImage();
}
bool ViewProviderImagePlane::isSvgFile(const char* filename) const
{
QFileInfo fi(QString::fromUtf8(filename));
return (fi.suffix().toLower() == QLatin1String("svg"));
}
QSizeF ViewProviderImagePlane::defaultSizeOfSvg(const char* filename) const
{
QSvgRenderer svg;
svg.load(QString::fromUtf8(filename));
return svg.defaultSize();
}
QSizeF ViewProviderImagePlane::getSizeInMM(const QImage& img) const
{
double xPixelsPerM = img.dotsPerMeterX();
double width = img.width();
width = width * 1000 / xPixelsPerM;
double yPixelsPerM = img.dotsPerMeterY();
double height = img.height();
height = height * 1000 / yPixelsPerM;
QSizeF sizef;
sizef.setWidth(width);
sizef.setHeight(height);
return sizef;
}
QSizeF ViewProviderImagePlane::pixelSize(const char* filename, const QSizeF& size) const
{
QImage tmp;
if (tmp.load(QString::fromUtf8(filename))) {
double xPixelsPerM = tmp.dotsPerMeterX();
double yPixelsPerM = tmp.dotsPerMeterY();
double width = size.width();
double height = size.height();
width = width * xPixelsPerM / 1000;
height = height * yPixelsPerM / 1000;
return {width, height};
}
return size;
}
void ViewProviderImagePlane::convertToSFImage(const QImage& img)
{
if (!img.isNull()) {
SoSFImage sfimg;
// convert to Coin bitmap
BitmapFactory().convert(img, sfimg);
texture->image = sfimg;
}
}
void ViewProviderImagePlane::updateData(const App::Property* prop)
{
Image::ImagePlane* pcPlaneObj = static_cast<Image::ImagePlane*>(pcObject);
if (prop == &pcPlaneObj->XSize || prop == &pcPlaneObj->YSize) {
float xsize = pcPlaneObj->XSize.getValue();
float ysize = pcPlaneObj->YSize.getValue();
resizePlane(xsize, ysize);
reloadIfSvg();
}
else if (prop == &pcPlaneObj->ImageFile) {
loadImage();
}
else {
Gui::ViewProviderGeometryObject::updateData(prop);
}
}