#include "dxfhelper.h" #include "dxfreader.h" #include #include DxfHelper::DxfHelper() { } double norm(double x, double y) { return sqrt(x * x + y * y); } QList DxfHelper::expandPolygon(QList polygon, float expand) { QList 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) { // 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); for(auto d: dxfReader.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; } QVector linepath; for(auto d: dxfReader.dxfLines) { //qDebug() << "line data:" << d.x1 << d.y1 << d.z1 << "," << d.x2 << d.y2 << d.z2; if(currentPos!=QPointF(d.x1, d.y1)) { if(!linepath.isEmpty()) { QList linelist; foreach(auto point, linepath) linelist.append(QVector3D(point)); linepath.clear(); linelist = expandPolygon(linelist, expandOffset); foreach(QVector3D point, linelist) { double x = point.x(); double y = point.y(); linepath.append(QPointF(x, y)); currentPos = QPointF(x, y); } dxfPaths.append(linepath); linepath.clear(); } linepath.append(QPointF(d.x1, d.y1)); linepath.append(QPointF(d.x2, d.y2)); currentPos = QPointF(d.x2, d.y2); } else { linepath.append(QPointF(d.x2, d.y2)); currentPos = QPointF(d.x2, d.y2); } } if(!linepath.isEmpty()) { QList linelist; foreach(auto point, linepath) linelist.append(QVector3D(point)); linepath.clear(); linelist = expandPolygon(linelist, expandOffset); foreach(QVector3D point, linelist) { double x = point.x(); double y = point.y(); linepath.append(QPointF(x, y)); currentPos = QPointF(x, y); } dxfPaths.append(linepath); linepath.clear(); } for(auto d: dxfReader.dxfArcs) { //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 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); } for(auto d: dxfReader.dxfCircles) { //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 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); // dxfPathList.append(path); } for(auto d: dxfReader.dxfEllipses) { // 起点角度要×ratio //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 ellipsepath; for(double i = 0; i <= 1; i += 0.003) { // TODO: 步长随图片大小调整 QPointF point = path.pointAtPercent(i); double x = point.x(); double y = point.y(); ellipsepath.append(point); currentPos=QPointF(x, y); } dxfPaths.append(ellipsepath); // dxfPathList.append(path); } for(auto d: dxfReader.dxfPolylines) { //qDebug() << "polylines data:" << d.m << d.n << d.flags << d.number << d.elevation; QList pointlist; QVector path; for(unsigned int i = 0; i < d.number; i++) { double x = dxfReader.dxfVertexs.at(vertexIndex).x; double y = dxfReader.dxfVertexs.at(vertexIndex).y; double z = dxfReader.dxfVertexs.at(vertexIndex).z; 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); } if(d.flags) { double x = pointlist.first().x(); double y = pointlist.first().y(); path.append(QPointF(x, y)); currentPos = QPointF(x, y); } dxfPaths.append(path); } // for(auto d: dxfReader.dxfVertexs) { // qDebug() << "vertexs data:" << d.x << d.y << d.z << d.bulge; // } for(auto d: dxfReader.dxfPoints) { //qDebug() << "points data:" << d.x << d.y << d.z; QVector path; path.append(QPointF(d.x, d.y)); dxfPaths.append(path); currentPos = QPointF(d.x, d.y); } for(auto d: dxfReader.dxfSplines) { //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; std::vector pointList; for(unsigned int i = 0; i < d.nControl; i++) { int x = dxfReader.dxfControlPoints.at(controlIndex).x; int y = dxfReader.dxfControlPoints.at(controlIndex).y; pointList.push_back(QVector2D(x, y)); currentPos = QPointF(x, y); controlIndex++; } QList templist; foreach(auto point, pointList) templist.append(point); templist = expandPolygon(templist, expandOffset); QVector inputList; foreach(auto point, templist) inputList.append(point.toVector2D()); inputList.push_front(inputList.first()); inputList.push_back(inputList.back()); // std::vector finalList(inputList.begin(), inputList.end()); // SplineHelper splineHelper(finalList, TypeCubicBSpline); // auto splinePath = splineHelper.getSplinePath(); // dxfPaths.append(splinePath); } // 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 path, dxfPaths) { for(int i = 0; i < path.length(); i++) { QPointF point = path.at(i); double x = point.x(); double y = point.y(); if(xmaxx) maxx = x; if(ymaxy) 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() { 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 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:" < DxfHelper::getDxfBorderList() const { return dxfBorderList; } QSize DxfHelper::getImageSize() const { return imageSize; } QList DxfHelper::getDxfPathList() const { return dxfPathList; } QVector > DxfHelper::getDxfPaths() const { return dxfPaths; } QList DxfHelper::getDxfLineList() const { return dxfLineList; } QList DxfHelper::getDxfRectList() const { return dxfRectList; } QList DxfHelper::getDxfArcList() const { return dxfArcList; } QList DxfHelper::getDxfCircleList() const { return dxfCircleList; } QList DxfHelper::getDxfEllipseList() const { return dxfEllipseList; } QList DxfHelper::getDxfPolylineList() const { return dxfPolylineList; } QList DxfHelper::getDxfSplineList() const { return dxfSplineList; } void DxfHelper::setExpandOffset(double value) { expandOffset = value; }