Análise e Exibição Interativa de Arquivos DXF em C# com Suporte a Zoom e Arrasto

  1. Princípio de Implementação das Fnucionalidades Principais

O processo envolve a análise do arquivo DXF usando a biblioteca netDxf, extração dos dados das entidades, renderização com um motor gráfico personalizado e implementação de operações interativas como zoom e arrasto.

2.1 Configuração do Ambiente

// Instalar pacotes necessários
Install-Package netDxf
Install-Package System.Numerics.Vectors

2.2 Design do Formulário Principal (WinForm)

using System;
using System.Drawing;
using System.Numerics;
using System.Windows.Forms;
using netDxf;
using netDxf.Entities;

namespace DXFViewer
{
    public partial class MainForm : Form
    {
        private DxfDocument documentoDxf;
        private Vector2 deslocamento = Vector2.Zero; // Vetor de deslocamento para arrasto
        private float fatorZoom = 1.0f; // Fator de escala para zoom
        private Point posicaoAnteriorMouse;

        public MainForm()
        {
            InitializeComponent();
            this.DoubleBuffered = true; // Reduzir flickering
            barraRolagemHorizontal.Maximum = 10000;
            barraRolagemVertical.Maximum = 10000;
        }
    }
}

2.3 Carregamento e Aálise do Arquivo DXF

// Carregar o arquivo DXF
private void CarregarDXF(string caminho)
{
    try
    {
        documentoDxf = DxfDocument.Load(caminho);
        AtualizarVisualizacao();
    }
    catch (Exception ex)
    {
        MessageBox.Show($"Falha no carregamento: {ex.Message}");
    }
}

// Processar as entidades do documento
private void ProcessarEntidades()
{
    listaEntidades.Clear();
    foreach (Entity entidade in documentoDxf.Entities)
    {
        if (entidade.Type == EntityType.Line)
        {
            var linha = (Line)entidade;
            listaEntidades.Add(new EntidadeDxf
            {
                Tipo = EntityType.Line,
                Pontos = new[] { linha.StartPoint, linha.EndPoint }
            });
        }
        else if (entidade.Type == EntityType.Circle)
        {
            var circulo = (Circle)entidade;
            listaEntidades.Add(new EntidadeDxf
            {
                Tipo = EntityType.Circle,
                Centro = circulo.Center,
                Raio = circulo.Radius
            });
        }
        // Adicionar tratamento para outros tipos de entidades...
    }
}

2.4 Motor Gráfico Personalizado

// Desenhar todas as entidades
private void DesenharEntidades(Graphics g)
{
    foreach (var entidade in listaEntidades)
    {
        Matrix3x2 transformacao = ObterMatrizTransformacao();
        switch (entidade.Tipo)
        {
            case EntityType.Line:
                DesenharLinha(g, (EntidadeLinha)entidade, transformacao);
                break;
            case EntityType.Circle:
                DesenharCirculo(g, (EntidadeCirculo)entidade, transformacao);
                break;
        }
    }
}

// Calcular a matriz de transformação
private Matrix3x2 ObterMatrizTransformacao()
{
    return Matrix3x2.CreateTranslation(-deslocamento.X, -deslocamento.Y) *
           Matrix3x2.CreateScale(fatorZoom, fatorZoom) *
           Matrix3x2.CreateTranslation(ClientSize.Width / 2, ClientSize.Height / 2);
}

2.5 Tratamento de Eventos Interativos

// Zoom com o scroll do mouse
private void MainForm_MouseWheel(object sender, MouseEventArgs e)
{
    float incremento = e.Delta > 0 ? 1.1f : 0.9f;
    fatorZoom *= incremento;
    AtualizarBarrasRolagem();
    Invalidate();
}

// Iniciar arrasto com o mouse
private void MainForm_MouseDown(object sender, MouseEventArgs e)
{
    posicaoAnteriorMouse = e.Location;
}

// Mover durante o arrasto
private void MainForm_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        Vector2 delta = new Vector2(e.X - posicaoAnteriorMouse.X, e.Y - posicaoAnteriorMouse.Y);
        deslocamento += delta;
        posicaoAnteriorMouse = e.Location;
        AtualizarBarrasRolagem();
        Invalidate();
    }
}

// Atualizar as barras de rolagem
private void AtualizarBarrasRolagem()
{
    barraRolagemHorizontal.Maximum = (int)(documentoDxf?.BoundingRectangle.Width * fatorZoom ?? 10000);
    barraRolagemVertical.Maximum = (int)(documentoDxf?.BoundingRectangle.Height * fatorZoom ?? 10000);
    barraRolagemHorizontal.Value = (int)deslocamento.X;
    barraRolagemVertical.Value = (int)deslocamento.Y;
}

  1. Expansão de Funcionalidades Avançadas

3.1 Suporte a Múltiplas Camadas

// Filtrar visibilidade das camadas
private void AtualizarVisibilidadeCamadas()
{
    var camadasAtivas = documentoDxf.Layers
        .Where(l => l.IsVisible)
        .Select(l => l.Name)
        .ToList();
    
    listaEntidades = listaEntidades.Where(e => camadasAtivas.Contains(e.Camada)).ToList();
}

3.2 Destaque na Seleção

// Detecção de clique do mouse
private void VerificarSelecao(Point posicaoCliente)
{
    Vector2 pos = Vector2.Transform(
        new Vector2(posicaoCliente.X, posicaoCliente.Y),
        Matrix3x2.Invert(ObterMatrizTransformacao())
    );

    foreach (var entidade in listaEntidades)
    {
        if (entidade.Tipo == EntityType.Line)
        {
            var linha = (EntidadeLinha)entidade;
            if (PontoProximoLinha(pos, linha.PontoInicial, linha.PontoFinal))
            {
                entidadeSelecionada = entidade;
                Invalidate();
                break;
            }
        }
    }
}

3.3 Otimização de Desempenho

// Carregamento em blocos para arquivos grandes
private void CarregarDXFGrande(string caminho)
{
    using (var stream = new FileStream(caminho, FileMode.Open))
    {
        var leitor = new DxfReader(stream);
        while (leitor.ReadNextSection())
        {
            if (leitor.SectionName == "ENTITIES")
            {
                while (!leitor.EndOfSection)
                {
                    var entidade = leitor.ReadEntity();
                    if (entidade != null)
                    {
                        listaEntidades.Add(ProcessarEntidade(entidade));
                        if (listaEntidades.Count % 100 == 0) // Atualizar interface a cada 100 entidades
                        {
                            this.Invoke((MethodInvoker)delegate { Invalidate(); });
                        }
                    }
                }
            }
        }
    }
}

  1. Exemplo de Design da Interface

+---------------------------------+
| Barra de Ferramentas [Abrir] [Salvar] [Sair] |
+---------------------------------+
| Painel de Controle de Camadas   |
| [Lista de camadas visíveis]     |
+---------------------------------+
| Área de Exibição Gráfica (PictureBox) |
| Zoom: 100% Deslocamento: (0,0)  |
+---------------------------------+
| Barra de Status                 |
| Coordenadas: (X:0,Y:0) Entidade selecionada: Nenhuma |
+---------------------------------+

  1. Estrutura do Projeto Completo

DXFViewer/
├── Controls/
│   ├── ControleCamadas.cs      # Controle para gerenciamento de camadas
│   └── SeletorEntidades.cs     # Seletor de entidades
├── Forms/
│   ├── MainForm.cs             # Formulário principal
│   └── SobreForm.cs            # Formulário de informações
├── Models/
│   ├── EntidadeDxf.cs          # Classe base para entidades
│   └── InfoCamada.cs           # Informações da camada
└── Resources/
    ├── icons/
    └── styles/

  1. Depuração e Testes

6.1 Ferramenta de Depuração de Coordenadas

// Exibir coordenadas em tempo real
private void AtualizarBarraStatus(Point posicaoCliente)
{
    Vector2 posicaoMundo = Vector2.Transform(
        new Vector2(posicaoCliente.X, posicaoCliente.Y),
        Matrix3x2.Invert(ObterMatrizTransformacao())
    );
    barraStatus.Text = $"Coordenadas do Mundo: ({posicaoMundo.X:F3}, {posicaoMundo.Y:F3})";
}

6.2 Detecção de Vazamentos de Memória

// Usar WeakReference para gerenciar entidades
private List<weakreference>> entidadesFracaReferencia = new();

// Ao adicionar uma entidade
entidadesFracaReferencia.Add(new WeakReference<entidadedxf>(entidade));
</entidadedxf></weakreference>

Tags: CSharp dxf netdxf windows-forms system-numerics

Publicado em 6-10 05:03 por Thomas