PlotterHMI/datafile/dxf/dxfhelper.cpp

661 lines
20 KiB
C++
Raw Normal View History

2024-02-06 06:19:53 +00:00
#include "dxfhelper.h"
#include "dxfreader.h"
#include <QImage>
#include <QPainter>
DxfHelper::DxfHelper()
{
}
double norm(double x, double y)
{
return sqrt(x * x + y * y);
}
QList<QVector3D> DxfHelper::expandPolygon(QList<QVector3D> polygon, float expand)
{
QList<QVector3D> new_polygon;
int len = polygon.length();
if(len<3||qFuzzyIsNull(expand)) return polygon;
bool repeatFlag = false;
if(polygon.first()==polygon.back()) {
repeatFlag = true;
polygon.removeLast();
len = polygon.length();
}
int convertNum = 0;
for (int i = 0; i < len; i++)
{
QVector3D p = polygon[i];
QVector3D p1 = polygon[i == 0 ? len - 1 : i - 1];
QVector3D p2 = polygon[i == len - 1 ? 0 : i + 1];
float v1x = p1.x() - p.x();
float v1y = p1.y() - p.y();
float n1 = norm(v1x, v1y);
float vv1x = v1x / n1;
float vv1y = v1y / n1;
float v2x = p2.x() - p.x();
float v2y = p2.y() - p.y();
float n2 = norm(v2x, v2y);
float vv2x = v2x / n2;
float vv2y = v2y / n2;
float vectorLen = -expand / sqrt((1 - (vv1x * vv2x + vv1y * vv2y)) / 2.0f);
float judge = v1x * v2y - v2x * v1y;
if (judge < 0) vectorLen *= -1;
if (judge < 0) convertNum++;
float vx = vv1x + vv2x;
float vy = vv1y + vv2y;
vectorLen = vectorLen / norm(vx, vy);
vx *= vectorLen;
vy *= vectorLen;
new_polygon.append(QVector3D(vx + p.x(), vy + p.y(), 0));
}
if(convertNum==len) {
new_polygon.clear();
for (int i = 0; i < len; i++)
{
QVector3D p = polygon[i];
QVector3D p1 = polygon[i == 0 ? len - 1 : i - 1];
QVector3D p2 = polygon[i == len - 1 ? 0 : i + 1];
float v1x = p1.x() - p.x();
float v1y = p1.y() - p.y();
float n1 = norm(v1x, v1y);
float vv1x = v1x / n1;
float vv1y = v1y / n1;
float v2x = p2.x() - p.x();
float v2y = p2.y() - p.y();
float n2 = norm(v2x, v2y);
float vv2x = v2x / n2;
float vv2y = v2y / n2;
float vectorLen = -expand / sqrt((1 - (vv1x * vv2x + vv1y * vv2y)) / 2.0f);
float vx = vv1x + vv2x;
float vy = vv1y + vv2y;
vectorLen = vectorLen / norm(vx, vy);
vx *= vectorLen;
vy *= vectorLen;
new_polygon.append(QVector3D(vx + p.x(), vy + p.y(), 0));
}
}
if(repeatFlag) new_polygon.append(new_polygon.first());
return new_polygon;
}
bool DxfHelper::generateDxf(const QString &fileName)
{
2024-03-22 07:58:53 +00:00
//获取引用块集合
QList<std::string> blockNameList;
getDxfReferenceBlocks(fileName,blockNameList);
2024-02-06 06:19:53 +00:00
// currentPos = QPointF(QRandomGenerator::global()->bounded(9999.99), QRandomGenerator::global()->bounded(9999.99));
currentPos = QPointF(9999.99, 9999.99);
vertexIndex = 0;
controlIndex = 0;
dxfPaths.clear();
DxfReader dxfReader(fileName);
2024-03-22 07:58:53 +00:00
QList<BlockDatas> blockDataList = dxfReader.getBlockDatas();
BlockDatas blockData;
//扫描判断哪个块的数据最多,其他块的数据全部不显示,只显示数据最多的块
for (int i = 0; i < blockDataList.size(); i++)
{
if(blockNameList.size() == 0)
{
blockData.dxfLines.append(blockDataList[i].dxfLines);
//blockData.dxfText.append(blockDataList[i].dxfText);
blockData.dxfArcs.append(blockDataList[i].dxfArcs);
blockData.dxfCircles.append(blockDataList[i].dxfCircles);
blockData.dxfEllipses.append(blockDataList[i].dxfEllipses);
blockData.dxfPolylines.append(blockDataList[i].dxfPolylines);
blockData.dxfPoints.append(blockDataList[i].dxfPoints);
blockData.dxfSplines.append(blockDataList[i].dxfSplines);
blockData.dxfVertexs.append(blockDataList[i].dxfVertexs);
}
else
{
if(blockNameList.contains(blockDataList[i].blockName) == true)
{
blockData.dxfLines.append(blockDataList[i].dxfLines);
//blockData.dxfText.append(blockDataList[i].dxfText);
blockData.dxfArcs.append(blockDataList[i].dxfArcs);
blockData.dxfCircles.append(blockDataList[i].dxfCircles);
blockData.dxfEllipses.append(blockDataList[i].dxfEllipses);
blockData.dxfPolylines.append(blockDataList[i].dxfPolylines);
blockData.dxfPoints.append(blockDataList[i].dxfPoints);
blockData.dxfSplines.append(blockDataList[i].dxfSplines);
blockData.dxfVertexs.append(blockDataList[i].dxfVertexs);
}
}
2024-02-06 06:19:53 +00:00
}
2024-03-22 07:58:53 +00:00
for(auto d: blockData.dxfText)
{
qDebug() << "text data:" << d.text.c_str() << d.angle << d.style.c_str() << d.height;
}
for(auto d: dxfReader.dxfLinetypes)
{
qDebug() << "linetypes data:" << d.name.c_str() << d.flags << d.pattern << d.description.c_str() << d.patternLength << d.numberOfDashes;
2024-02-06 06:19:53 +00:00
}
QVector<QPointF> linepath;
2024-03-22 07:58:53 +00:00
for(auto d: blockData.dxfLines)
{
2024-02-06 06:19:53 +00:00
//qDebug() << "line data:" << d.x1 << d.y1 << d.z1 << "," << d.x2 << d.y2 << d.z2;
2024-03-22 07:58:53 +00:00
linepath.append(QPointF(d.x1, d.y1));
linepath.append(QPointF(d.x2, d.y2));
2024-02-06 06:19:53 +00:00
dxfPaths.append(linepath);
linepath.clear();
}
2024-03-22 07:58:53 +00:00
for(auto d: blockData.dxfArcs)
{
2024-02-06 06:19:53 +00:00
//qDebug() << "arcs data:" << d.cx << d.cy << d.cz << d.angle1 << d.angle2 << d.radius;
double cx = d.cx;
double cy = d.cy;
// double cz = d.cz;
double angle1 = d.angle1;
double angle2 = d.angle2;
double radius = d.radius;
radius = radius + expandOffset;
QPainterPath path;
double startXPos = cx + cos(abs(angle1)*M_PI/180)*radius;
double startYPos = cy + sin(abs(angle1)*M_PI/180)*radius;
path.moveTo(startXPos, startYPos);
double angleStart ,anglePassed;
angleStart = angle1;
if(angleStart>=180) angleStart = angleStart-360;
anglePassed = angleStart-angle2;
if(angleStart<180) angleStart = -angleStart;
if(anglePassed<-360) anglePassed = anglePassed+360;
QRectF rect(cx-radius, cy-radius, 2*radius, 2*radius);
path.arcTo(rect, angleStart, anglePassed);
QVector<QPointF> arcpath;
for(double i = 0; i <= 1; i += 0.003) { // TODO: 步长随图片大小调整
QPointF point = path.pointAtPercent(i);
double x = point.x();
double y = point.y();
arcpath.append(point);
currentPos=QPointF(x, y);
}
dxfPaths.append(arcpath);
// dxfPathList.append(path);
}
2024-03-22 07:58:53 +00:00
for(auto d: blockData.dxfCircles)
{
2024-02-06 06:19:53 +00:00
//qDebug() << "circle data:" << d.cx << d.cy << d.cz << d.radius;
double cx = d.cx;
double cy = d.cy;
// double cz = d.cz;
double radius = d.radius;
radius = radius + expandOffset;
QPainterPath path;
path.moveTo(cx+radius, cy);
path.arcTo(cx-radius, cy-radius, 2*radius, 2*radius, 0, 360);
QVector<QPointF> circlepath;
for(double i = 0; i <= 1; i += 0.003) { // TODO: 步长随图片大小调整
QPointF point = path.pointAtPercent(i);
double x = point.x();
double y = point.y();
circlepath.append(point);
currentPos=QPointF(x, y);
}
dxfPaths.append(circlepath);
}
2024-03-22 07:58:53 +00:00
for(auto d: blockData.dxfEllipses)
{
// 起点角度要×ratio
2024-02-06 06:19:53 +00:00
//qDebug() << "ellipses data:" << d.cx << d.cy << d.cz << d.mx << d.my << d.mz << d.ratio << d.angle1 << d.angle2;
double cx = d.cx;
double cy = d.cy;
// double cz = d.cz;
double mx = d.mx;
double my = d.my;
// double mz = d.mz;
double ratio = d.ratio;
double angle1 = d.angle1;
double angle2 = d.angle2;
double rab = sqrt((cx- mx)*(cx - mx) +(cy - my)*(cy - my));
double resy = (expandOffset*(my-cy))/rab + my;
double resx = (expandOffset*(mx-cx))/rab + mx;
mx = resx;
my = resy;
QPainterPath path;
double angle_1 = angle1;
double angle_2 = angle2;
while(angle_1>=3.14&&angle_2>=6.28) {
angle_1 -= M_PI;
angle_2 -= M_PI;
}
angle_1 = angle_1*180/M_PI;
angle_2 = angle_2*180/M_PI;
double angleStart ,anglePassed;
angleStart = angle_1;
if(angleStart>=180) angleStart = angleStart-360;
anglePassed = angleStart-angle_2;
if(angleStart<180) angleStart = -angleStart;
if(anglePassed<-360) anglePassed = anglePassed+360;
if(abs(anglePassed)<1) anglePassed = 360;
double c_x = cx;
double c_y = cy;
double dl = sqrt(mx*mx+my*my);
double ds = dl*ratio;
double rx;
double ry;
if(qFuzzyIsNull(mx)) {
rx = ds; ry = dl;
angleStart += 90;
} else {
rx = dl; ry = ds;
}
double angle=angleStart;
if(angle<0) angle=-angle;
else if(angle>=0) angle = 360-angle;
//if(!qFuzzyCompare(abs(anglePassed),360)) angle *= ratio;
if(!qFuzzyCompare(float(anglePassed),(float)360)) angle *= ratio;
double a=qDegreesToRadians(angle);
double R=rx*ry/sqrt(pow(rx*sin(a),2)+pow(ry*cos(a),2)); //计算对应角度的半径
double startXPos=c_x+R*cos(a);
double startYPos=c_y+R*sin(a);
path.moveTo(startXPos, startYPos);
//qDebug() << c_x << c_y << rx << ry << angleStart << anglePassed << angle;
path.arcTo(c_x-rx, c_y-ry, 2*rx, 2*ry, angleStart, anglePassed);
QVector<QPointF> ellipsepath;
2024-03-22 07:58:53 +00:00
for(double i = 0; i <= 1; i += 0.003)
{ // TODO: 步长随图片大小调整
2024-02-06 06:19:53 +00:00
QPointF point = path.pointAtPercent(i);
double x = point.x();
double y = point.y();
ellipsepath.append(point);
currentPos=QPointF(x, y);
}
dxfPaths.append(ellipsepath);
}
2024-03-22 07:58:53 +00:00
for(auto d: blockData.dxfPolylines)
{
2024-02-06 06:19:53 +00:00
//qDebug() << "polylines data:" << d.m << d.n << d.flags << d.number << d.elevation;
QList<QVector3D> pointlist;
QVector<QPointF> path;
for(unsigned int i = 0; i < d.number; i++) {
2024-03-22 07:58:53 +00:00
double x = blockData.dxfVertexs.at(vertexIndex).x;
double y = blockData.dxfVertexs.at(vertexIndex).y;
double z = blockData.dxfVertexs.at(vertexIndex).z;
2024-02-06 06:19:53 +00:00
pointlist.append(QVector3D(x, y, z));
vertexIndex++;
}
pointlist = expandPolygon(pointlist, expandOffset);
foreach(QVector3D point, pointlist) {
double x = point.x();
double y = point.y();
path.append(QPointF(x, y));
currentPos = QPointF(x, y);
}
2024-03-22 07:58:53 +00:00
if(d.flags && pointlist.size() > 0) {
2024-02-06 06:19:53 +00:00
double x = pointlist.first().x();
double y = pointlist.first().y();
path.append(QPointF(x, y));
currentPos = QPointF(x, y);
}
dxfPaths.append(path);
}
2024-03-22 07:58:53 +00:00
QVector<QPointF> path;
for(int i = 0; i < blockData.dxfVertexs.size(); i++)
{
QPointF point;
//qDebug() << "vertexs data:" << d.x << d.y << d.z << d.bulge;
point.setX(blockData.dxfVertexs.at(i).x);
point.setY(blockData.dxfVertexs.at(i).y);
path.append(point);
if(path.size() == 2)
{
if(i+1 < blockData.dxfVertexs.size())
{
QPointF point1;
//qDebug() << "vertexs data:" << d.x << d.y << d.z << d.bulge;
point1.setX(blockData.dxfVertexs.at(i+1).x);
point1.setY(blockData.dxfVertexs.at(i+1).y);
if(point1 != point)
{
path.append(point1);
}
}
dxfPaths.append(path);
path.clear();
}
}
// for(auto d: blockData.dxfVertexs)
// {
// QPointF point;
// //qDebug() << "vertexs data:" << d.x << d.y << d.z << d.bulge;
// point.setX(d.x);
// point.setY(d.y);
// path.append(point);
// if(path.size() == 2)
// {
// dxfPaths.append(path);
// path.clear();
// }
2024-02-06 06:19:53 +00:00
// }
2024-03-22 07:58:53 +00:00
for(auto d: blockData.dxfPoints)
{
2024-02-06 06:19:53 +00:00
//qDebug() << "points data:" << d.x << d.y << d.z;
QVector<QPointF> path;
path.append(QPointF(d.x, d.y));
dxfPaths.append(path);
currentPos = QPointF(d.x, d.y);
}
2024-03-22 07:58:53 +00:00
// for(auto d: blockData.dxfSplines)
// {
2024-02-06 06:19:53 +00:00
//qDebug() << "splines data:" << d.nFit << d.flags << d.degree << d.nKnots << d.nControl << d.tangentEndX << d.tangentEndY << d.tangentEndZ << d.tangentStartX << d.tangentStartY << d.tangentStartZ;
2024-03-22 07:58:53 +00:00
// std::vector<QVector2D> pointList;
// for(unsigned int i = 0; i < d.nControl; i++)
// {
// int x = blockData.dxfControlPoints.at(controlIndex).x;
// int y = blockData.dxfControlPoints.at(controlIndex).y;
// pointList.push_back(QVector2D(x, y));
// currentPos = QPointF(x, y);
// controlIndex++;
// }
// QList<QVector3D> templist;
// foreach(auto point, pointList) templist.append(point);
// templist = expandPolygon(templist, expandOffset);
// QVector<QVector2D> inputList;
// foreach(auto point, templist) inputList.append(point.toVector2D());
// inputList.push_front(inputList.first());
// inputList.push_back(inputList.back());
2024-02-06 06:19:53 +00:00
// std::vector<QVector2D> finalList(inputList.begin(), inputList.end());
// SplineHelper splineHelper(finalList, TypeCubicBSpline);
// auto splinePath = splineHelper.getSplinePath();
// dxfPaths.append(splinePath);
2024-03-22 07:58:53 +00:00
// }
2024-02-06 06:19:53 +00:00
// for(auto d: dxfReader.dxfControlPoints) {
// qDebug() << "control points data:" << d.w << d.x << d.y << d.z;
// }
// for(auto d: dxfReader.dxfXLines) {
// qDebug() << "XLines data:" << d.bx << d.by << d.bz << d.dx << d.dy << d.dz;
// }
// for(auto d: dxfReader.dxfRays) {
// qDebug() << "rays data:" << d.bx << d.by << d.bz << d.dx << d.dy << d.dz;
// }
// for(auto d: dxfReader.dxfFitPoints) {
// qDebug() << "fit points data:" << d.x << d.y << d.z;
// }
// for(auto d: dxfReader.dxfHatchs) {
// qDebug() << "hatchs data:" << d.angle << d.scale << d.solid << d.originX << d.originY << d.pattern.c_str() << d.numLoops;
// }
// for(auto d: dxfReader.dxfHatchLoops) {
// qDebug() << "hatchLoops data:" << d.numEdges;
// }
// for(auto d: dxfReader.dxfHatchEdges) {
// qDebug() << "hatchEdges data:" << d.cx << d.cy << d.mx << d.my << d.x1 << d.y1 << d.x2 << d.y2 << d.ccw << d.nFit << d.ratio << d.angle1 << d.angle2 << d.degree << d.nKnots << d.radius << d.defined << d.weights << d.nControl << d.periodic << d.rational << d.vertices << d.fitPoints << d.endTangentX << d.endTangentY << d.endTangentY << d.controlPoints << d.startTangentX << d.startTangentY;
// }
return true;
}
void DxfHelper::matchDXFSize()
{
double minx = __DBL_MAX__;
double maxx = __DBL_MIN__;
double miny = __DBL_MAX__;
double maxy = __DBL_MIN__;
foreach (QVector<QPointF> path, dxfPaths) {
for(int i = 0; i < path.length(); i++) {
QPointF point = path.at(i);
double x = point.x();
double y = point.y();
if(x<minx) minx = x;
if(x>maxx) maxx = x;
if(y<miny) miny = y;
if(y>maxy) maxy = y;
}
}
int width = maxx - minx;
int height = maxy - miny;
imageSize = QSize(width, height);
dxfBorderList.clear();
dxfBorderList.append(minx);
dxfBorderList.append(miny);
dxfBorderList.append(maxx);
dxfBorderList.append(maxy);
}
QImage DxfHelper::generateDXFImage()
{
2024-03-22 07:58:53 +00:00
// //放大数据
// QVector<QVector<QPointF>> dxfPathscp;
// foreach (QVector<QPointF> path, dxfPaths)
// {
// QVector<QPointF> pathcp;
// for(int i = 0; i < path.length(); i++)
// {
// QPointF point = path.at(i);
// double x = point.x()*10;
// double y = point.y()*10;
// pathcp.append(QPointF(x,y));
// }
// dxfPathscp.append(pathcp);
// }
// dxfPaths.clear();
// dxfPaths = dxfPathscp;
2024-02-06 06:19:53 +00:00
matchDXFSize();
double minx = dxfBorderList.at(0);
double miny = dxfBorderList.at(1);
int penwidth = imageSize.width()/400;
int border = penwidth;
QImage image((imageSize.width()+2*border), (imageSize.height()+2*border), QImage::Format_ARGB32);
image.fill(Qt::white);
QPainter p(&image);
p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); // 抗锯齿和使用平滑转换算法
QPen pen;
if(penwidth<1) penwidth = 1;
pen.setWidth(penwidth);
pen.setColor(Qt::black);
p.setPen(pen);
QPainterPath painterpath;
foreach (QVector<QPointF> path, dxfPaths) {
for(int i = 0; i < path.length(); i++) {
double x = path.at(i).x()-minx;
double y = path.at(i).y()-miny;
y = imageSize.height()-y;
x += border;
y += border;
QPointF point(x, y);
if(i == 0) painterpath.moveTo(point);
else painterpath.lineTo(point);
}
// dxfPathList.append(painterpath);
}
//qDebug() << "[" << __FILE__ << ":" << __LINE__ << "]\t"<< "dxf path length:" <<dxfPaths.length();
p.drawPath(painterpath);
p.end();
return image;
}
QList<double> DxfHelper::getDxfBorderList() const
{
return dxfBorderList;
}
2024-03-22 07:58:53 +00:00
bool DxfHelper::getDxfReferenceBlocks(const QString &fileName, QList<std::string> &blockNameList)
{
blockNameList.clear();
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug() << "Failed to open file:" << fileName;
return false;
}
int addFlag = 0;
int blockFlag = 0;
int getFlag = 0;
int endFlag = 0;
QTextStream in(&file);
while (!in.atEnd())
{
std::string line = in.readLine().remove(QRegExp("\\s")).toStdString();
// 处理每一行数据
if(line == "AcDbBlockReference")//块被引用的标志
{
addFlag = 1;
continue;
}
if(addFlag == 1)
{
if(line == "AcDbBlockBegin")//块开始标志
{
blockFlag = 1;
endFlag = 0;
continue;
}
if(blockFlag == 1)
{
if(line == "2")//下一行为块名称
{
getFlag = 1;
continue;
}
if(getFlag == 1)//块名称
{
if(blockNameList.contains(line) == false)
//if(!line.empty() && line[0] != '*')
{
blockNameList.append(line);
}
getFlag = 0;
continue;
}
}
if(line == "AcDbBlockEnd")//块结束标志
{
blockFlag = 0;
endFlag = 1;
continue;
}
}
}
if(endFlag == 0 && addFlag == 1)
{
if(blockNameList.size() > 0)
{
blockNameList.removeLast();
}
}
file.close();
return true;
}
2024-02-06 06:19:53 +00:00
QSize DxfHelper::getImageSize() const
{
return imageSize;
}
QList<QPainterPath> DxfHelper::getDxfPathList() const
{
return dxfPathList;
}
QVector<QVector<QPointF> > DxfHelper::getDxfPaths() const
{
return dxfPaths;
}
QList<DXFLine> DxfHelper::getDxfLineList() const
{
return dxfLineList;
}
QList<DXFRect> DxfHelper::getDxfRectList() const
{
return dxfRectList;
}
QList<DXFArc> DxfHelper::getDxfArcList() const
{
return dxfArcList;
}
QList<DXFCircle> DxfHelper::getDxfCircleList() const
{
return dxfCircleList;
}
QList<DXFEllipse> DxfHelper::getDxfEllipseList() const
{
return dxfEllipseList;
}
QList<DXFPolyline> DxfHelper::getDxfPolylineList() const
{
return dxfPolylineList;
}
QList<DXFSpline> DxfHelper::getDxfSplineList() const
{
return dxfSplineList;
}
void DxfHelper::setExpandOffset(double value)
{
expandOffset = value;
}