工程图PDF标题栏与目录生成器

生成PDF工程图,合并PDF文件,添加文字、图片与自定义标题栏,并生成目录。

--by Captdam @ 2024-09-21 02:40 GMT edited

[en] Here is the English version of this article

Also on GitHub: https://github.com/captdam/DrawingTitleblock

起因

我在工作中时常需要绘制机械施工图纸。虽然我所使用的SoldWorks与Fusion在建模上没有什么问题,但是它们对图纸的标题栏的支持却有限。

工作中我最早接触使用的CAD是SolidWorks。在制作工程图时,我首先选择一张空白的工程图模板,接下来再添加结构与零件。SolidWorks提供了一些可以插入标题栏的参数,例如当前页码、总页数、作者。但是,这里也有不少限制:

之后公司为了节约成本换成了Fusion。Fusion在制图方面比SolidWorks更难用,除了上面这些问题以为,Fusion还:

一张纸质工程图

第一次尝试

在网上冲浪寻找制作SolidWorks与Fusion的标题栏的方法后,我果断放弃了。与其花时间死磕,不如另辟蹊径自己造车。我决定写一个程序来帮我制作工程图的标题栏。

我在网上找到了一个可以帮我编辑PDF的JS库PDF-Lib,于是我就基于这个库写了一个Web app,我觉得Web app很合适,因为有这些优势:

现在,我将让CAD生成不带标题栏的图纸(或者只包括零件比例)。我将使用我自己写的这个程序来添加标题栏制作最终的施工图。

作为第一次尝试,这个程序将执行这些步骤:

  1. 导入图纸文件PDF,两张图片(公司与客户的商标)和目录文件CSV。
  2. 为图纸文件的每一页添加标题栏。首先使用一些列的包含在这个程序里面的SVG绘图指令画出标题栏的框架。然后再从目录文件中读取每一页的信息,例如工程名、零件名、修改日期、作者,并写在特定位置(具体书写的位置则在程序代码中定义了)。接下来,特定位置添加商标图片。最后,插入一个+1计数器作为页码。
  3. 在文件开头插入一张空白页并添加标题栏与信息等。接下来,使用特定规则通过目录文件中信息生成目录列表。

下面展示了工程图原图、目录与带有标题栏的最终完成图:

工程图原图
工程图原图
目录
目录
带有标题栏的最终完成图
带有标题栏的最终完成图

第二次尝试

第一次尝试写出来的程序能够生成我想要的图纸,但是这个程序的设计和代码一点也不优雅,也有很多限制。

我重写这个程序不仅是为了让这个程序更适用,也是为了解决Fusion的一些问题。

对于SolidWorks来说,图纸是独立于零件或结构的。在创建空白图纸后,我可以随便添加毫无关联的不同零件与结构到图纸中。但是对于Fusion,图纸是和顶层结构挂钩或零件的。我必须要选择一个顶层结构挂钩或零件作为图纸的主题来创建图纸。接下来,我只能在这张图纸中包含那个顶层结构的子结构或零件。这也导致了一些新问题:

Fusion实际上会把顶层结构重新插入图纸,然后再隐蔽选择的子结构或零件以外的其它部分
Fusion实际上会把顶层结构重新插入图纸,然后再隐蔽选择的子结构或零件以外的其它部分

因此,我们更倾向把设计拆分成小的结构或单独零件并分别建立工程图,然后再将它们合并起来生成最终工程图。

新的程序仍然使用CSV文件作为目录,但是将支持多个PDF图纸文件与任意数量的PNG、JPEG图片文件。

简单有利于规律。新的程序摒弃了参数与标题栏的概念。与其从目录文件中提取出参数并放置在提前设定好的地方,不如让目录文件来定义在哪些地方放置怎样的文字或图片。与其使用固定的标题栏,不如直接用一张包含了标题栏的线条框架与文字,且背景透明的PNG文件来代替。

确切来讲,新的程序已经脱离标题栏生成器的范畴,而是一个可以合并PDF并插入图片的通用PDF编辑器了。

我们在之前定义了一套关于参数位置的规则,但现在这套规则变成了可以在目录文件中自定义,这也造成了短板与问题:

目录文件格式

每一行都代表了一页图纸。

Type - 种类

每一行开头表示了当前页的种类,可以是特定图纸文件中的特定一页,也可以是特定尺寸的空白页。


@BLANK,width,height
@BLANK,17,11
	

如果第一栏是“@BLANK”,程序将会为此页创建一张空白的图纸,并使用接下来两栏的内容作为尺寸(单位:英寸)。在这个例子中,我们创建了一个17x11英寸(横向Tabloid)的空白页。


file,page,rotation
a.pdf,5,90
	

否则,程序将从图纸文件中复制出来特定一页。第一第二栏分别是源图纸的文件名与需要复制的页码(第一页是1),第三栏为旋转角度。在这个例子中,我们复制“a.pdf”的第5页并旋转90度。

提示:旋转角度只改变PDF文件的观测角度,并不会实际旋转/修改PDF。

之后可以是一个或多个项目,项目可以是:

提示:原点为左下角(旋转前)。

Text - 文字

使用‘T’作为文字开头,并附上x-y坐标、文字高度、行高(都是英寸为单位)、RGBA颜色(0.0到1.0)、旋转角度(度)参数和要打印的文字。另外,可以使用“\n”作为分行。


T,x,y,h,lh,r,g,b,a,rotate,'text\nand new line'
T,1,3,0.1,0.15,1,0,0,0.5,20,Some text
	

上面的例子将会在(x = 1, y = 3)的位置使用0.1寸字体与0.15寸行高的半透明红打印“Some text”。

Picture - 图片

使用‘P’作为图片开头,并附上x-y坐标、图片尺寸(都是英寸为单位)、旋转角度(度)参数和图片文件名。图片可以是PNG或JPEG格式,PNG可以是背景透明的。


P,x,y,w,h,rotate,filename
P,9,5,4,2,45,icon.png
	

上面的例子将会在(x = 9, y = 5)的位置使插入文件名为“icon.png”的图片。图片宽4英寸宽,高2英寸,并旋转45度。

Index - 目录

使用‘I’作为目录开头,并附与文字项目相同的参数和目录项目参数,其中ref_col为将要包括的项目在目录文件中的列数(最左边为第一列,计数时包括空白的列),ref_rowStart为目录的起始行(最上为第一行),ref_rowLen为目录的长度。


I,x,y,h,lh,r,g,b,a,rotate,ref_col,ref_rowStart,ref_rowLen
I,1,10,0.1,0.15,0,0,0,1,0,5,2,20
	

上面的例子将会在(x = 1, y = 10)的位置使用0.1寸字体与0.15寸行高的黑色打印目录。目录将包含从第2行开始的20行中的第5列的内容。

Dummy - 伪项目

使用‘X’作为伪项目开头,这个特殊的项目可以让我们在接下来一栏中放入我们想要放在目录文件中但是却不希望放进最终成品图纸中的东西,例如注释。


X,whatever
X,TODO: update in next reversion
	

上面的例子就展示了一个在目录文件中留下注释的使用场景。

目录文件中的空白栏

目录文件中可以插入任意的空白栏来帮助排版(以及方便在表格软件中快速编辑),下面两个例子生成的效果是完全相同的。


@BLANK,17,11,T,1,3,0.1,0.15,1,0,0,0.5,20,Some text,,,T,1,3,0.1,0.15,1,0,0,0.5,20,More text
@BLANK,17,11,,,T,1,3,0.1,0.15,1,0,0,0.5,,,,20,Some text,T,1,3,0.1,0.15,1,0,0,0.5,20,More text
	

例子

下面将展示将2张工程图原图、一张PNG扫描件、一张JPEG照片合并为一份工程图并添加标题栏与目录。为了简便展示,这里将使用一个迷你版的标题栏而不是标准的标题栏。

源文件

目录文件
目录文件 - CSV源文件:example.csv
图纸1
图纸1 - PDF源文件:1.pdf
图纸2
图纸2 - PDF源文件:2.pdf
标题栏模板
标题栏模板 - PNG源文件:tb.png
参考文件
参考文件 - PNG源文件:r1.png
照片
照片 - JPEG源文件:photo.jpg

目录

我们将图纸的第一页将作为目录页,我们将需要:

  1. 创建一张17x11的空白页。

    
    @BLANK,17,11
    			
  2. 插入标题栏。我们将带有alpha通道的背景透明的PNG文件插入到原点(0,0),并将图片大小设置为页面大小。

    
    P,0,0,17,11,0,tb.png
    			
  3. 在特定地方插入工程名、本页标题、页码、总页数、作者与版本号。

    
    T,13,1.05,0.25,0.3,0,0,0,1,0,Naval Gun Model	// Project name
    T,13,0.6,0.25,0.3,0,0,0,1,0,Index		// Page title
    T,16,0.23,0.16,0.2,0,0,0,1,0,0			// Page number
    T,16.4,0.23,0.16,0.2,0,0,0,1,0,/ 6		// Page count
    T,13,0.23,0.16,0.2,0,0,0,1,0,Captdam		// Author
    T,15.2,0.23,0.16,0.2,0,0,0,1,0,1		// Reversion
    			
  4. 在本页(封面)顶部写上大号的工程名,插入目录的标题。

    
    T,1,10,0.35,0.4,0,0,0,1,0,Naval Gun Model
    T,1,9.3,0.16,0.2,0,0,0,1,0,Title
    T,4,9.3,0.16,0.2,0,0,0,1,0,Page
    			
  5. 从目录文件中提取信息生成目录。这里我们将生成两项目录:第33列的每页的标题、第44列的每页的页码。目录将从第2行(也就是第二页)开始,这样就可以跳过被作为目录的第一页(也就是当前页),持续6行。

    
    I,1,9,0.16,0.2,0,0,0,1,0,33,2,6
    I,4,9,0.16,0.2,0,0,0,1,0,44,2,6
    			

我们将把图纸源文件“1.pdf”中的两页图纸作为最终工程图的第2页与第3页,把图纸源文件“2.pdf”中的两页图纸作为最终工程图的第5页与第6页。我们将需要:

  1. 导入特定文件中的特定页,这个例子将导入“1.pdf”的第1页,不进行任何旋转。

    
    1.pdf,1,0
    			
  2. 和目录页的第2到4步相同,插入标题栏与相关参数。

    
    P,0,0,17,11,0,tb.png				// Titleblack
    T,13,1.05,0.25,0.3,0,0,0,1,0,Naval Gun Model	// Project name
    T,13,0.6,0.25,0.3,0,0,0,1,0,Side plates		// Page title
    T,16,0.23,0.16,0.2,0,0,0,1,0,A1			// Page number
    T,16.4,0.23,0.16,0.2,0,0,0,1,0,/ 6		// Page count
    T,13,0.23,0.16,0.2,0,0,0,1,0,Captdam		// Author
    T,15.2,0.23,0.16,0.2,0,0,0,1,0,0		// Reversion
    			

在第4页,我们希望可以插入一张扫描文件“r1.png”作为参考图。因为这张图自带标题栏,我们就没必要为这一页添加我们自己的标题栏。我们将需要:

  1. 创建一张17x11的空白页。

    
    @BLANK,17,11
    			
  2. 虽然我们不需要标题栏相关的参数,但是我们仍然需要在目录文件中包含这些参数来生成目录。我们可以使用“X”伪项目来在目录文件中包含这些信息,但是这些信息在这里将不会被放入图纸中。

    
    X,Naval Gun Model	// Project name
    X,Model reference	// Page title
    X,A3			// Page number
    X,/ 6			// Page count
    X,Joe Doe		// Author
    X,As-is			// Reversion
    			
  3. 在原点(0,0)插入图片“r1.png”,尺寸与图纸尺寸相等,使这张扫描件的图片铺满当前页。

    
    P,0,0,17,11,0,r1.png
    			
  4. 用半透明的红色和一点角度打一个水印“Reference Design”表示这是参考图纸。

    
    T,4.5,4,1,1.5,1,0,0,0.5,20,REFERENCE DESIGN
    			

在最后一页,我们想要添加一张成品照片,这一页可以包含我们的标题栏。我们将需要:

  1. 创建一张17x11的空白页。

    
    @BLANK,17,11
    			
  2. 和目录页的第2到4步相同,插入标题栏与相关参数。

    
    P,0,0,17,11,0,tb.png				// Titleblack
    T,13,1.05,0.25,0.3,0,0,0,1,0,Naval Gun Model	// Project name
    T,13,0.6,0.25,0.3,0,0,0,1,0,Product photo	// Page title
    T,16,0.23,0.16,0.2,0,0,0,1,0,C1			// Page number
    T,16.4,0.23,0.16,0.2,0,0,0,1,0,/ 6		// Page count
    T,13,0.23,0.16,0.2,0,0,0,1,0,Captdam		// Author
    T,15.2,0.23,0.16,0.2,0,0,0,1,0,0		// Reversion
    			
  3. 在合适的地方以合适的尺寸插入照片“photo.jpg”。

    
    P,2.5,1.5,12,9,0,photo.jpg
    			

最终图纸

下面就是最后生成的PDF工程图:

最终PDF工程图
最终PDF工程图 - PDF源文件:result.pdf