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:
puzzlesion 2025-09-12 17:20:36 +08:00
parent 03ddec8caa
commit fc79d59e53
8 changed files with 24699 additions and 0 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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)

View 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.")

Binary file not shown.