#include <iostream>
#include <vector>
#include <fstream>
#include "opencv2/opencv.hpp"
#include <algorithm>
using namespace cv;
using namespace std;
struct Vertex { float x, y, z; };
vector<Vertex> readSTL(const string& filename) {
vector<Vertex> vertices;
ifstream file(filename, ios::binary);
if (!file.is_open()) {
cerr << "Error opening file" << endl;
return vertices;
}
// 跳过80字节头部
file.seekg(80);
uint32_t triCount;
file.read(reinterpret_cast<char*>(&triCount), sizeof(uint32_t));
for (uint32_t i = 0; i < triCount; ++i) {
file.seekg(12, ios::cur); // 跳过法向量
for (int j = 0; j < 3; ++j) { // 读取三个顶点
Vertex v;
file.read(reinterpret_cast<char*>(&v.x), sizeof(float));
file.read(reinterpret_cast<char*>(&v.y), sizeof(float));
file.read(reinterpret_cast<char*>(&v.z), sizeof(float));
vertices.push_back(v);
}
file.seekg(2, ios::cur); // 跳过属性
}
return vertices;
}
void generateView(
const vector<Vertex>& vertices,
const function<Point2f(const Vertex&)>& projector,
const string& outputName,
int imgSize = 1000)
{
// 计算投影范围
vector<Point2f> points;
for (const auto& v : vertices) {
points.push_back(projector(v));
}
/*auto[x_min, x_max] = minmax_element(
points.begin(), points.end(),
[](const Point2f& a, const Point2f& b) { return a.x < b.x; });
auto[y_min, y_max] = minmax_element(
points.begin(), points.end(),
[](const Point2f& a, const Point2f& b) { return a.y < b.y; });*/
// 计算投影范围
auto x_extremes = minmax_element(
points.begin(), points.end(),
[](const Point2f& a, const Point2f& b) { return a.x < b.x; });
auto x_min = x_extremes.first; // 最小元素迭代器
auto x_max = x_extremes.second; // 最大元素迭代器
auto y_extremes = minmax_element(
points.begin(), points.end(),
[](const Point2f& a, const Point2f& b) { return a.y < b.y; });
auto y_min = y_extremes.first;
auto y_max = y_extremes.second;
// 计算缩放和平移
float scale = 0.9 * imgSize / max(
(*x_max).x - (*x_min).x, // 解引用迭代器获取Point2f对象
(*y_max).y - (*y_min).y
);
float offsetX = (imgSize - ((*x_max).x - (*x_min).x) * scale) / 2 - (*x_min).x * scale;
float offsetY = (imgSize - ((*y_max).y - (*y_min).y) * scale) / 2 - (*y_min).y * scale;
/*float scale = 0.9 * imgSize / max(x_max->x - x_min->x, y_max->y - y_min->y);
float offsetX = (imgSize - (x_max->x - x_min->x) * scale) / 2 - x_min->x * scale;
float offsetY = (imgSize - (y_max->y - y_min->y) * scale) / 2 - y_min->y * scale;*/
// 创建图像并绘制
Mat img(imgSize, imgSize, CV_8UC3, Scalar(255, 255, 255));
for (size_t i = 0; i < vertices.size(); i += 3) {
for (int j = 0; j < 3; ++j) {
const Vertex& v1 = vertices[i + j];
const Vertex& v2 = vertices[i + (j + 1) % 3];
Point2f p1 = projector(v1);
Point2f p2 = projector(v2);
// 坐标系转换(OpenCV的Y轴向下)
Point ip1(
cvRound(p1.x * scale + offsetX),
imgSize - cvRound(p1.y * scale + offsetY));
Point ip2(
cvRound(p2.x * scale + offsetX),
imgSize - cvRound(p2.y * scale + offsetY));
line(img, ip1, ip2, Scalar(0, 0, 0), 1);
}
}
imwrite(outputName, img);
}
int main() {
string filename = "G:/工作/模板类/现场返回模板/MCH-模板-标定/模型/CG面.stl";
auto vertices = readSTL(filename);
if (vertices.empty()) return 1;
// 生成三视图
generateView(vertices, [](const Vertex& v) { return Point2f(v.x, v.y); }, "G:/工作/模板类/现场返回模板/MCH-模板-标定/模型/front.bmp");
generateView(vertices, [](const Vertex& v) { return Point2f(v.x, v.z); }, "G:/工作/模板类/现场返回模板/MCH-模板-标定/模型/top.bmp");
generateView(vertices, [](const Vertex& v) { return Point2f(v.y, v.z); }, "G:/工作/模板类/现场返回模板/MCH-模板-标定/模型/side.bmp");
return 0;
}
这段代码生成的3视图通过两点间的连线生成3视图看起来无法得到产品好看规整的轮廓如何优化?
最新发布