feat(python): add scripts for CAD to PDF conversion and block finding
This commit introduces two new feature scripts to the Aspose_CAD_Python project: - print_cad_to_pdf.py: A script to export CAD drawings to PDF format, providing a direct way to generate printable documents. - step1_find_block_coordinates.py: A utility to find and list the coordinates of specific blocks within a CAD file, which is a crucial first step for automated plotting and data extraction. Additionally, relevant documentation in .specstory has been added to reflect these new capabilities.
This commit is contained in:
parent
03ddec8caa
commit
fc79d59e53
4168
.specstory/history/2025-09-10_09-01Z-打印dxf图纸时文本缺失.md
Normal file
4168
.specstory/history/2025-09-10_09-01Z-打印dxf图纸时文本缺失.md
Normal file
File diff suppressed because it is too large
Load Diff
1121
.specstory/history/2025-09-10_10-21Z-分析报错原因.md
Normal file
1121
.specstory/history/2025-09-10_10-21Z-分析报错原因.md
Normal file
File diff suppressed because it is too large
Load Diff
6357
.specstory/history/2025-09-10_12-16Z-使用aposecad打印pdf图纸脚本.md
Normal file
6357
.specstory/history/2025-09-10_12-16Z-使用aposecad打印pdf图纸脚本.md
Normal file
File diff suppressed because it is too large
Load Diff
6004
.specstory/history/2025-09-11_03-16Z-实现aposecad功能的步骤.md
Normal file
6004
.specstory/history/2025-09-11_03-16Z-实现aposecad功能的步骤.md
Normal file
File diff suppressed because it is too large
Load Diff
6848
.specstory/history/2025-09-11_04-12Z-查找指定坐标打印pdf的示例.md
Normal file
6848
.specstory/history/2025-09-11_04-12Z-查找指定坐标打印pdf的示例.md
Normal file
File diff suppressed because it is too large
Load Diff
94
01_Aspose_CAD_Python/print_cad_to_pdf.py
Normal file
94
01_Aspose_CAD_Python/print_cad_to_pdf.py
Normal file
@ -0,0 +1,94 @@
|
||||
import aspose.cad as cad
|
||||
import os
|
||||
import argparse
|
||||
|
||||
def find_shx_files(fonts_dir):
|
||||
"""Finds all .shx files in a directory."""
|
||||
shx_files = []
|
||||
for root, _, files in os.walk(fonts_dir):
|
||||
for file in files:
|
||||
if file.lower().endswith('.shx'):
|
||||
shx_files.append(os.path.join(root, file))
|
||||
return shx_files
|
||||
|
||||
def print_cad_to_pdf(input_dwg, output_pdf, fonts_dir):
|
||||
"""
|
||||
Converts a CAD drawing (DWG) to a PDF file, using specified custom fonts.
|
||||
|
||||
:param input_dwg: Path to the input DWG file.
|
||||
:param output_pdf: Path to save the output PDF file.
|
||||
:param fonts_dir: Directory containing custom SHX fonts.
|
||||
"""
|
||||
print(f"Input DWG: {input_dwg}")
|
||||
print(f"Output PDF: {output_pdf}")
|
||||
print(f"Fonts directory: {fonts_dir}")
|
||||
|
||||
# Load the DWG file
|
||||
try:
|
||||
image = cad.Image.load(input_dwg)
|
||||
print("Successfully loaded DWG file.")
|
||||
except Exception as e:
|
||||
print(f"Error loading DWG file: {e}")
|
||||
return
|
||||
|
||||
# Create an instance of CadRasterizationOptions
|
||||
rasterization_options = cad.imageoptions.CadRasterizationOptions()
|
||||
|
||||
# Set page size to match drawing size and disable scaling to preserve coordinates
|
||||
rasterization_options.no_scaling = True
|
||||
rasterization_options.page_width = float(image.width)
|
||||
rasterization_options.page_height = float(image.height)
|
||||
|
||||
rasterization_options.layouts = ["Model"]
|
||||
|
||||
# Set to color mode. 1 corresponds to USE_OBJECT_COLOR.
|
||||
# We use the integer value directly as the enum type is not exposed in a public module.
|
||||
rasterization_options.draw_type = 1
|
||||
|
||||
# Find and set SHX fonts
|
||||
shx_font_files = find_shx_files(fonts_dir)
|
||||
if shx_font_files:
|
||||
print(f"Found {len(shx_font_files)} SHX font files.")
|
||||
rasterization_options.shx_fonts = shx_font_files
|
||||
else:
|
||||
print("Warning: No SHX font files found in the specified directory.")
|
||||
|
||||
# Create an instance of PdfOptions
|
||||
pdf_options = cad.imageoptions.PdfOptions()
|
||||
pdf_options.vector_rasterization_options = rasterization_options
|
||||
|
||||
# Save the PDF
|
||||
try:
|
||||
image.save(output_pdf, pdf_options)
|
||||
print(f"Successfully converted to PDF: {output_pdf}")
|
||||
except Exception as e:
|
||||
print(f"Error saving PDF file: {e}")
|
||||
finally:
|
||||
# Dispose image - The python wrapper seems to handle this automatically.
|
||||
# image.dispose()
|
||||
print("Image resources are managed automatically.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Convert CAD drawing to PDF with custom fonts.")
|
||||
parser.add_argument("input_file", help="Path to the input CAD file (e.g., DWG, DXF).")
|
||||
args = parser.parse_args()
|
||||
|
||||
input_file_path = args.input_file
|
||||
|
||||
# Define other paths
|
||||
workspace_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
fonts_folder_path = os.path.join(workspace_root, '03_Python_OpenSource_DXF', 'fonts')
|
||||
|
||||
# Generate output file path based on input file name
|
||||
base_name = os.path.basename(input_file_path)
|
||||
file_name, _ = os.path.splitext(base_name)
|
||||
output_file_path = os.path.join(os.path.dirname(__file__), f'{file_name}_output.pdf')
|
||||
|
||||
|
||||
# Check if files/folders exist
|
||||
if not os.path.exists(input_file_path):
|
||||
print(f"Error: Input file not found at {input_file_path}")
|
||||
elif not os.path.isdir(fonts_folder_path):
|
||||
print(f"Error: Fonts directory not found at {fonts_folder_path}")
|
||||
else:
|
||||
print_cad_to_pdf(input_file_path, output_file_path, fonts_folder_path)
|
||||
107
01_Aspose_CAD_Python/step1_find_block_coordinates.py
Normal file
107
01_Aspose_CAD_Python/step1_find_block_coordinates.py
Normal file
@ -0,0 +1,107 @@
|
||||
import aspose.cad as cad
|
||||
import os
|
||||
from aspose.cad.fileformats.cad import CadImage
|
||||
from aspose.cad.fileformats.cad.cadobjects import CadInsertObject
|
||||
|
||||
def set_license():
|
||||
"""
|
||||
Tries to find and apply an Aspose.CAD license.
|
||||
"""
|
||||
try:
|
||||
from aspose.cad import License
|
||||
license = License()
|
||||
# The SetLicense method expects the name of the license file.
|
||||
# Common names are Aspose.CAD.lic or Aspose.Total.lic.
|
||||
# It should be placed in the folder with the script, or you can specify a full path.
|
||||
# As we don't have the license file, this will likely fail silently
|
||||
# or work if the user has placed it correctly.
|
||||
license.set_license("Aspose.CAD.lic")
|
||||
print("License set successfully (if found).")
|
||||
except Exception as e:
|
||||
print(f"License not set or error: {e}. Running in evaluation mode.")
|
||||
|
||||
def find_block_coordinates(dwg_path, printable_blocks):
|
||||
"""
|
||||
Finds specified blocks in a DWG file and returns their coordinates and layout.
|
||||
|
||||
:param dwg_path: Path to the DWG file.
|
||||
:param printable_blocks: A dictionary of block names to find.
|
||||
:return: A list of dictionaries, each containing block info.
|
||||
"""
|
||||
if not os.path.exists(dwg_path):
|
||||
print(f"Error: File not found at {dwg_path}")
|
||||
return []
|
||||
|
||||
found_blocks = []
|
||||
|
||||
with cad.Image.load(dwg_path) as image:
|
||||
# Based on the file `extract_lines_correct.py`, the correct object is returned directly.
|
||||
# The issue might be specific to the environment or the DWG file itself.
|
||||
# Let's use the exact loading method from the working example.
|
||||
cad_image = cad.fileformats.cad.CadImage.load(dwg_path)
|
||||
|
||||
try:
|
||||
print(f"Successfully loaded image. Type: {type(cad_image).__name__}")
|
||||
|
||||
# A DWG's paper space layouts are stored in blocks with names like "*Paper_Space"
|
||||
# Model space is in "*Model_Space"
|
||||
# We iterate through these special blocks to find the block insertions.
|
||||
if hasattr(cad_image, 'blocks'):
|
||||
print("Iterating through cad_image.blocks...")
|
||||
for block in cad_image.blocks:
|
||||
# Layout blocks often start with '*'
|
||||
if block.name.startswith('*'):
|
||||
layout_name = block.name
|
||||
for entity in block.entities:
|
||||
if isinstance(entity, CadInsertObject):
|
||||
block_name = entity.name
|
||||
if block_name in printable_blocks:
|
||||
min_point = entity.min_point
|
||||
max_point = entity.max_point
|
||||
|
||||
block_info = {
|
||||
"block_name": block_name,
|
||||
"layout": layout_name,
|
||||
"min_point": (min_point.x, min_point.y),
|
||||
"max_point": (max_point.x, max_point.y)
|
||||
}
|
||||
found_blocks.append(block_info)
|
||||
print(f" Found block '{block_name}' in layout/block '{layout_name}'")
|
||||
else:
|
||||
print("Attribute 'blocks' not found on CadImage object.")
|
||||
finally:
|
||||
# Manually dispose of the image if CadImage.load was used
|
||||
cad_image.dispose()
|
||||
|
||||
return found_blocks
|
||||
|
||||
if __name__ == "__main__":
|
||||
# It's a good practice to set the license at the start of the application
|
||||
set_license()
|
||||
|
||||
# Define the blocks we are interested in, based on 思路.MD
|
||||
PRINTABLE_BLOCKS = {
|
||||
"A$C2EB80DB8": ("A1", "portrait"),
|
||||
"A$C1CC9093B": ("A1", "landscape"),
|
||||
"A$C6D564680": ("A2", "portrait"),
|
||||
"新块": ("A3", "landscape"),
|
||||
"新块1": ("A4", "portrait"),
|
||||
}
|
||||
|
||||
# Path to the test DWG file
|
||||
dwg_file_path = os.path.join("04_Test_Files", "图签测试.dwg")
|
||||
|
||||
print(f"Loading DWG file: {dwg_file_path}")
|
||||
|
||||
blocks_data = find_block_coordinates(dwg_file_path, PRINTABLE_BLOCKS)
|
||||
|
||||
print("\n--- Found Blocks Summary ---")
|
||||
if blocks_data:
|
||||
for block in blocks_data:
|
||||
print(f"Block: {block['block_name']}")
|
||||
print(f" Layout: {block['layout']}")
|
||||
print(f" Min Point: {block['min_point']}")
|
||||
print(f" Max Point: {block['max_point']}")
|
||||
print("-" * 20)
|
||||
else:
|
||||
print("No specified blocks were found in the DWG file.")
|
||||
BIN
01_Aspose_CAD_Python/图签测试_output.pdf
Normal file
BIN
01_Aspose_CAD_Python/图签测试_output.pdf
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user