DXFViewer进行中2 -> 直线 解析+渲染 ✅已完成

发布于:2025-05-07 ⋅ 阅读:(25) ⋅ 点赞:(0)

DXFViewer进行中 : ->封装OpenGL -> 解析DXF直线-CSDN博客https://blog.csdn.net/qq_25547755/article/details/147723906

   上篇博文

解析dxf直线635条

1. DXFViewer.h

#pragma once
#include "Application.h"
#include <stdio.h>
#include <iostream>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/string_cast.hpp>
#include "../Entity/Line.h" 
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <Windows.h>

class DXFViewer :public Application
{ 

public:	  
    std::string UTF8ToGB(const char* str)
    {
        std::string result;
        WCHAR* strSrc;
        LPSTR szRes;

        //获得临时变量的大小
        int i = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
        strSrc = new WCHAR[i + 1];
        MultiByteToWideChar(CP_UTF8, 0, str, -1, strSrc, i);

        //获得临时变量的大小
        i = WideCharToMultiByte(CP_ACP, 0, strSrc, -1, NULL, 0, NULL, NULL);
        szRes = new CHAR[i + 1];
        WideCharToMultiByte(CP_ACP, 0, strSrc, -1, szRes, i, NULL, NULL);

        result = szRes;
        delete[]strSrc;
        delete[]szRes;

        return result;
    }

    // 去除前后空格
    std::string trim(const std::string& str) {
        auto first = str.find_first_not_of(" \t\r\n");
        auto last = str.find_last_not_of(" \t\r\n");
        return (first == std::string::npos) ? "" : str.substr(first, last - first + 1);
    }

    // 读取组码-值对
    bool ReadCodes(std::ifstream& file, std::string& code, std::string& value) {
        if (!std::getline(file, code)) return false;
        if (!std::getline(file, value)) return false;

        std::string strCode = UTF8ToGB(code.c_str()).c_str();
        std::string strValue = UTF8ToGB(value.c_str()).c_str();
        code = trim(strCode);
        value = trim(strValue);
        return true;
    }   

    glm::vec3 GetColorByLayer(const std::string& layer)
    {
        static std::map<std::string, glm::vec3> layerColors = {
            { "0",     {1.0f, 1.0f, 1.0f} },
            { "WALL",  {1.0f, 0.0f, 0.0f} },
            { "DOOR",  {0.0f, 1.0f, 0.0f} },
            { "WINDOW",{0.0f, 0.5f, 1.0f} }
        };

        auto it = layerColors.find(layer);
        return (it != layerColors.end()) ? it->second : glm::vec3(1.0); // 默认为白色
    }

    /// <summary>
    /// 读取直线
    /// </summary> 
    void ReadLine(const std::string& filename)
    {
        std::ifstream file(filename, std::ios::binary);
        if (!file.is_open()) {
            std::cerr << "无法打开文件: " << filename << std::endl;
            return;
        }

        std::string code, value;
        std::string currentLayer;

        std::map<std::string, std::string> lineEntity;

        const std::map<std::string, std::string> codeToKey = {
            { "10", "StartX" }, { "20", "StartY" }, { "30", "StartZ" },
            { "11", "EndX"   }, { "21", "EndY"   }, { "31", "EndZ"   }
        };

        while (ReadCodes(file, code, value)) {
            // 记录当前图层(可用于后续颜色处理)
            if (code == "100" && value == "AcDbEntity") {
                while (ReadCodes(file, code, value)) {
                    if (code == "8") {
                        currentLayer = value;
                        break;
                    }
                }
            }

            // 解析 AcDbLine
            if (code == "100" && value == "AcDbLine") {
                lineEntity.clear();

                while (ReadCodes(file, code, value)) {
                    auto it = codeToKey.find(code);
                    if (it != codeToKey.end()) {
                        lineEntity[it->second] = value;
                    }

                    if (lineEntity.size() == 6) {
                        // 读取完毕后再解析 + 添加直线
                        glm::vec3 start(
                            std::stof(lineEntity["StartX"]),
                            std::stof(lineEntity["StartY"]),
                            std::stof(lineEntity["StartZ"])
                        );
                        glm::vec3 end(
                            std::stof(lineEntity["EndX"]),
                            std::stof(lineEntity["EndY"]),
                            std::stof(lineEntity["EndZ"])
                        );

                        glm::vec3 color = GetColorByLayer(currentLayer); // 可选

                        m_line.AddLine(start, end, color);
                        break;
                    }
                }
            }
        }

        file.close();
    }

	virtual void  Startup()
	{   
        std::string filename = R"(C:\Users\ml\Desktop\Drawing1.dxf)";

        // 解析文件
        ReadLine(filename);

		printf("读取了直线 %d 条\r\n",(m_line.GetSize()/2));
		m_line.Init();
		 
	}; 

	virtual void  Render()
	{		  
		m_line.Render(m_camera);
       
	}; 
	virtual void  Shutdown()
	{
		printf("Shutdown\r\n");
	};

private:
    Line  m_line;
};

2. Line.h

#pragma once
#include "Entity.h"
#include "glm/glm.hpp"
#include "../Shader/Shader_P3_C3.h"
#include "../Core/OrthoCamera.h"
#include <vector>

class Line  
{
public:
	Line()
	{
		m_vao = -1;
		m_vbo = -1;
	};
	~Line()
	{
		glDeleteVertexArrays(1, &m_vao);
		glDeleteBuffers(1, &m_vbo);
	};


	virtual void Init()  // 数据准备
	{
		// 1.准备Shader
		m_shader.Initialize();
		 
		// Shader应用绑定顶点缓冲区数据
		glGenVertexArrays(1, &m_vao);

		glBindVertexArray(m_vao);
		// 创建显存并向顶点缓冲填充数据
		glGenBuffers(1, &m_vbo);
		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
		glBufferData(GL_ARRAY_BUFFER, m_vertices.size() * sizeof(Vertex), m_vertices.data(), GL_STATIC_DRAW);
		glVertexAttribPointer(m_shader.m_position, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
		glEnableVertexAttribArray(m_shader.m_position);
		glVertexAttribPointer(m_shader.m_color, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(3 * sizeof(float)));
		glEnableVertexAttribArray(m_shader.m_color);

		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindVertexArray(0);
		 

	} 

	void AddLine(glm::vec3 start, glm::vec3 end, glm::vec3 color) {
		m_vertices.push_back({ start.x, start.y, start.z, color.r, color.g, color.b });
		m_vertices.push_back({ end.x, end.y, end.z, color.r, color.g, color.b });
	 
	}

	virtual void Render(const OrthoCamera& camera) // 绘制
	{ 
		m_shader.Begin();
		glBindVertexArray(m_vao);
		glUniformMatrix4fv(m_shader.m_mvp, 1, GL_FALSE, (const GLfloat*)&camera.GetViewProjectionMatrix());
		glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(m_vertices.size()));
		m_shader.End();
		
	}

	typedef struct Vertex
	{
		float x, y, z;
		float r, g, b;

	} Vertex;

	unsigned int GetSize()
	{
		return m_vertices.size();
	}

private:
	GLuint         m_vao;
	GLuint         m_vbo;
	Shader_P3_C3   m_shader;

	std::vector<Vertex> m_vertices;	 

};

3.Shader_P3_C3.h

#pragma once
#include "Shader.h"
class Shader_P3_C3:public Shader
{

public:
    Shader_P3_C3()
	{
		m_mvp      = -1;
		m_position = -1;
		m_color    = -1;
	};

	~Shader_P3_C3()
	{
	};

	virtual bool  Initialize()
	{
       const char* vs = R"(
               #version 330
               uniform mat4 MVP;
               in vec3 vPos;
               in vec3 vCol;

               out vec3 color;
               void main()
               {
                  gl_Position = MVP * vec4(vPos, 1.0);
                  color = vCol;
               }
          )";

        const char* ps = R"(
                #version 330
                in vec3 color;
                out vec4 fragment;
                void main()
                {
                     fragment = vec4(color, 1.0); 
                }
          )";

        bool    res = CreateShader(vs, ps);

        if (res)
        {
            m_mvp      = glGetUniformLocation(m_shaderId, "MVP");
            m_position = glGetAttribLocation(m_shaderId,  "vPos");
            m_color    = glGetAttribLocation(m_shaderId,  "vCol");;
        }	

        return true;
	}

public:
	int m_mvp;
    int m_position;
	int m_color;
};