10年世界杯冠军_梅西2018年世界杯 - kefulq.com

ODB++资料解析

美国篮球世界杯 2026-01-08 16:29:09

ODB++文件是由VALOR提出的一种ASCII码,双向传输文件。奥宝公司和康代公司的设备都是用的ODB++格式进行PCB的生产和检测。

对ODB++文件进行解析把数据栅格化很重要,查了网上找不到一个成熟能用的ODB++文件解析代码。自己上手写了一个。

当前解析一些载板,软硬结合板都没有问题。

解析思路:

文件注释:

代码思路:

Commom下只有两个文件,主要存放一些常用的算法,一些常量定义,一些枚举类型

Job目录下存放跟ODB++资料紧密相关的类

这部分内容需要了解ODB++资料才能理解。

实际上就是ODB+文件是一个JOB类,包含有step等等信息,一般整个板就是一个panel,panel是由set组合成的,set又是有一个pcs组合来的,pcs就是对应我们的PCB单板了。

odbGeometry 存放ODB++的图元,主要用到的pad(焊盘)segment(线)surface (铜皮)arc(弧线)

和其他的一些辅助类,所有图元类继承自图元基类odbBase.

就这几个解析我手上几个G的ODB资料都没问题。

需要解析奥宝康代等扫描机,曝光机资料的可私信我。

(二)用C++重写的odb++模块

支持C#和Python调用

C++函数接口

#pragma once

#include "ecam_global.h"

#include

#include

#include

#include

#include

#include

class ICAM;

enum class eCamType

{

ODBPP, //奥宝康代普遍使用的AOI导入格式

AOIIMG, //奥宝特有的AOI格式

RLE, //行程编码

GERBER, //行业通用格式,精度问题导致在高端板逐渐被弃用

};

extern "C" {

class ECAM_EXPORT ECAM

{

public:

ECAM(eCamType type);

~ECAM();

///

/// 设置文件路径,支持导入tgz格式文件 && 已解压出来的资料文件夹

///

///

void SetFilePath(QString path);

///

/// 预解析,解析资料的整体信息,包括Panel,Step,Layer,Matrix以获取层别等信息

///

///

int PreAnalyze();

///

/// 获取板子长宽信息,默认单位是um

///

///

QRectF GetBoundingBox();

///

/// 选择解析出来的层别,只支持一个信号层,可支持多个通孔层

///

/// Step名称,如PNL,PCS

/// 信号层名称

/// 通孔层名称

///

int Select(QString step, QString signalLayer, QStringList drillLayer);

///

/// 解析资料,分析资料的特征信息

///

///

int Analyze();

///

/// 绘制图像

///

/// 图像宽

/// 图像高

/// 绘制出来的图像

/// 绘制的区域大小

///

int Draw(int imgWidth, int imgHeight, QImage& img, QRectF& drawRect);

///

///

///

///

///

///

int DrawProfile(double pageScale, QString path);

int Draw(int imgWidth, int imgHeight, QString path, QRectF& drawRect);

int Draw(int imgWidth, int imgHeight, uchar** imgData, QRectF& drawRect);

std::vector GetSignalLayerNames();

std::vector GetStepNames() const;

void ClearJob();

void FreeMem();

private:

std::shared_ptr icam;

};

//#pragma region 以下接口为导出到C#使用的接口,接口使用同上一致

int ECAM_EXPORT InitEcam(int type);

int ECAM_EXPORT SetFilePath(const char* path);

int ECAM_EXPORT PreAnalyze();

int ECAM_EXPORT GetStepNames(char*& stepNames);

int ECAM_EXPORT GetSignalLayerNames(char*& signalLayerNames);

int ECAM_EXPORT Select(const char* step, const char* signalLayer, const char* drillLayer);

int ECAM_EXPORT Analyze();

int ECAM_EXPORT GetBoundingBox(double& x, double& y, double& width, double& height);

int ECAM_EXPORT DrawProfile(double pageScale, const char* path);

int ECAM_EXPORT DrawImageFile(int x, int y, int drawWidth, int drawHeight, int imgWidth, int imgHeight, const char* path);

int ECAM_EXPORT DrawImageData(int x, int y, int drawWidth, int drawHeight, int imgWidth, int imgHeight, uchar** imgData);

int ECAM_EXPORT ClearJob();

void ECAM_EXPORT FreeMem();

//int ECAM_EXPORT ExportImage(uchar** image, int& width, int& height, int& stride);

//#pragma endregion

}

C#调用接口

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Runtime.InteropServices;

namespace ECAMCSharp

{

public partial class ECAM

{

[DllImport("ECAMd.dll", EntryPoint = "InitEcam", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

public static extern int InitEcam(int type);

[DllImport("ECAMd.dll", EntryPoint = "SetFilePath", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

public static extern int SetFilePath(string path);

[DllImport("ECAMd.dll", EntryPoint = "PreAnalyze", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

public static extern int PreAnalyze();

[DllImport("ECAMd.dll", EntryPoint = "GetStepNames", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

public static extern int GetStepNames(out IntPtr stepNames);

[DllImport("ECAMd.dll", EntryPoint = "GetSignalLayerNames", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

public static extern int GetSignalLayerNames(out IntPtr signalLayerNames);

[DllImport("ECAMd.dll", EntryPoint = "Select", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

public static extern int Select(string step, string signalLayer, string drillLayer);

[DllImport("ECAMd.dll", EntryPoint = "Analyze", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

public static extern int Analyze();

[DllImport("ECAMd.dll", EntryPoint = "GetBoundingBox", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

public static extern int GetBoundingBox(ref double x, ref double y, ref double width, ref double height);

[DllImport("ECAMd.dll", EntryPoint = "DrawProfile", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

public static extern int DrawProfile(double pageScale, string path);

[DllImport("ECAMd.dll", EntryPoint = "DrawImageFile", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

public static extern int DrawImageFile(int x, int y, int drawWidth, int drawHeight, int imgWidth, int imgHeight, string path);

[DllImport("ECAMd.dll", EntryPoint = "DrawImageData", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

public static extern int DrawImageData(int x, int y, int drawWidth, int drawHeight, int imgWidth, int imgHeight, out IntPtr imgData);

[DllImport("ECAMd.dll", EntryPoint = "ClearJob", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

public static extern int ClearJob();

[DllImport("ECAMd.dll", EntryPoint = "FreeMem", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

public static extern void FreeMem();

}

}

ECAM测试程序

C#测试程序