This commit is contained in:
parent
b8d5db01b9
commit
3db8214819
|
@ -4,14 +4,14 @@
|
||||||
# (c) andreika <prometheus.pcb@gmail.com>
|
# (c) andreika <prometheus.pcb@gmail.com>
|
||||||
############################################################################################
|
############################################################################################
|
||||||
|
|
||||||
import os, sys, re
|
import os, sys, re, math
|
||||||
import configparser
|
import configparser
|
||||||
import gzip
|
import gzip
|
||||||
|
|
||||||
### Unfortunately PyVRML97 (vrml.vrml97) is not capable of properly processing Altium-exported VRML-files...
|
### Unfortunately PyVRML97 (vrml.vrml97) is not capable of properly processing Altium-exported VRML-files...
|
||||||
|
|
||||||
if len(sys.argv) < 3:
|
if len(sys.argv) < 3:
|
||||||
print "Error! Please specify the place+board files and vrml filename."
|
print ("Error! Please specify the place+board files and vrml filename.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
mergePlaceFile = sys.argv[1]
|
mergePlaceFile = sys.argv[1]
|
||||||
mergeBoardFile = sys.argv[2]
|
mergeBoardFile = sys.argv[2]
|
||||||
|
@ -32,42 +32,57 @@ with open(mergePlaceFile, 'rb') as fmp:
|
||||||
m = {"name": name, "x": m[1], "y": m[2], "rot": rot, "path": config[name]["Prefix"] }
|
m = {"name": name, "x": m[1], "y": m[2], "rot": rot, "path": config[name]["Prefix"] }
|
||||||
fragments.append(m)
|
fragments.append(m)
|
||||||
|
|
||||||
print "* Starting merge of " + str(len(fragments)) + " board fragments..."
|
print ("* Starting merge of " + str(len(fragments)) + " board fragments...")
|
||||||
|
|
||||||
outf = gzip.open(fileOutName, 'wb')
|
outf = gzip.open(fileOutName, 'wb')
|
||||||
outf.write("#VRML V2.0 utf8\n")
|
outf.write("#VRML V2.0 utf8\n")
|
||||||
|
|
||||||
pat_hdr = re.compile('^#VRML.*')
|
pat_hdr = re.compile('^#VRML.*')
|
||||||
pat_idx = re.compile(r'(DEF|USE)\s+(Shape|_)(\w)')
|
pat_idx = re.compile(r'(DEF|USE)\s+(Shape|_)(\w)')
|
||||||
pat_trans = re.compile(r'(translation)\s+([+\-0-9\.]+)\s+([+\-0-9\.]+)')
|
pat_kicad_transform = re.compile(r'DEF\s+(\w+)\s+Transform.*')
|
||||||
|
|
||||||
def trans_repl(m):
|
|
||||||
x = float(m.group(2))
|
|
||||||
y = float(m.group(3))
|
|
||||||
return m.group(1) + " " + str(x + off_x_mm) + " " + str(y + off_y_mm)
|
|
||||||
|
|
||||||
fId = 1
|
fId = 1
|
||||||
for frag in fragments:
|
for frag in fragments:
|
||||||
# convert to mm
|
# convert to mm
|
||||||
off_x_mm = float(frag["x"]) * 25.4
|
off_x_mm = float(frag["x"]) * 25.4
|
||||||
off_y_mm = float(frag["y"]) * 25.4
|
off_y_mm = float(frag["y"]) * 25.4
|
||||||
# todo: apply module rotations
|
|
||||||
rot = float(frag["rot"])
|
rot = float(frag["rot"])
|
||||||
fileName = frag["path"] + "-vrml.wrl"
|
fileName = frag["path"] + "-vrml.wrl"
|
||||||
print "* Adding " + frag["name"] + " (" + fileName + ") at (" + str(off_x_mm) + "," + str(off_y_mm) + "), rot=" + str(rot) + "..."
|
z_offset = 0
|
||||||
|
was_global_transform = False
|
||||||
|
fragId = str(fId).zfill(2)
|
||||||
|
|
||||||
|
print ("* Adding " + frag["name"] + " (" + fileName + ") at (" + str(off_x_mm) + "," + str(off_y_mm) + "), rot=" + str(rot) + "...")
|
||||||
with open(fileName, 'rb') as f:
|
with open(fileName, 'rb') as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
line = line.rstrip()
|
line = line.rstrip()
|
||||||
# skip the headers (we write our own because there should be only 1 header)
|
# skip the headers (we write our own because there should be only 1 header)
|
||||||
if pat_hdr.match(line):
|
if pat_hdr.match(line):
|
||||||
continue
|
continue
|
||||||
fragId = str(fId).zfill(2)
|
# add global transformation for the module
|
||||||
|
if not was_global_transform:
|
||||||
|
# for bottom-aligned kicad VRML files, we need to shift them down - to align it with the top surface of the board
|
||||||
|
if pat_kicad_transform.match(line):
|
||||||
|
print ("* Kicad VRML detected!")
|
||||||
|
# the board is 1.6 mm thick?
|
||||||
|
# todo: this is a 'hack'
|
||||||
|
z_offset = -1.6
|
||||||
|
outf.write("DEF TX" + frag["name"] + " Transform {\n")
|
||||||
|
outf.write(" center 0 0 0\n")
|
||||||
|
outf.write(" rotation 0 0 1 " + str(math.radians(rot)) + "\n")
|
||||||
|
outf.write(" scale 1.0 1.0 1.0\n")
|
||||||
|
outf.write(" scaleOrientation 0 0 1 0\n")
|
||||||
|
outf.write(" translation " + str(off_x_mm) + " " + str(off_y_mm) + " " + str(z_offset) + "\n")
|
||||||
|
outf.write(" children [\n")
|
||||||
|
was_global_transform = True
|
||||||
|
|
||||||
line = pat_idx.sub(r'\g<1> \g<2>' + fragId + '\g<3>', line)
|
line = pat_idx.sub(r'\g<1> \g<2>' + fragId + '\g<3>', line)
|
||||||
line = pat_trans.sub(trans_repl, line)
|
|
||||||
outf.write(line + "\n")
|
outf.write(line + "\n")
|
||||||
f.close()
|
f.close()
|
||||||
|
if was_global_transform:
|
||||||
|
outf.write("] }\n")
|
||||||
fId = fId + 1
|
fId = fId + 1
|
||||||
|
|
||||||
outf.close()
|
outf.close()
|
||||||
|
|
||||||
print "Done!"
|
print ("Done!")
|
||||||
|
|
|
@ -341,7 +341,6 @@ subprocess.call([sys.executable, "bin/create_3d_components.py",
|
||||||
board_cfg_path,
|
board_cfg_path,
|
||||||
board_misc_path_name + "-3D.wrl.gz"])
|
board_misc_path_name + "-3D.wrl.gz"])
|
||||||
|
|
||||||
"""
|
|
||||||
print ("Rendering a 3D-model of the board components...")
|
print ("Rendering a 3D-model of the board components...")
|
||||||
subprocess.call([node_bin, "bin/render_vrml/render_components.js",
|
subprocess.call([node_bin, "bin/render_vrml/render_components.js",
|
||||||
board_misc_path_name + "-3D.wrl.gz",
|
board_misc_path_name + "-3D.wrl.gz",
|
||||||
|
@ -369,7 +368,6 @@ subprocess.call([sys.executable, "bin/gen_iBOM.py",
|
||||||
"./ibom-data",
|
"./ibom-data",
|
||||||
rotations,
|
rotations,
|
||||||
board_path_name + "-ibom.html"])
|
board_path_name + "-ibom.html"])
|
||||||
"""
|
|
||||||
|
|
||||||
print ("Cleaning up...")
|
print ("Cleaning up...")
|
||||||
delete_file(board_cfg_path)
|
delete_file(board_cfg_path)
|
||||||
|
|
|
@ -20,7 +20,7 @@ function createBoardImg(pcbImg, outlineImg, compImg) {
|
||||||
var boardImg = new PNG({
|
var boardImg = new PNG({
|
||||||
width: Math.max(pcbImg.width, outlineImg.width, compImg.width),
|
width: Math.max(pcbImg.width, outlineImg.width, compImg.width),
|
||||||
height: Math.max(pcbImg.height, outlineImg.height, compImg.height) });
|
height: Math.max(pcbImg.height, outlineImg.height, compImg.height) });
|
||||||
var pcbOffY = (pcbImg.height < boardImg.height) ? -(boardImg.height - pcbImg.height) : 0;
|
var pcbOffY = (pcbImg.height < outlineImg.height) ? -(outlineImg.height - pcbImg.height) : 0;
|
||||||
// Blit the pcbImg using the outlineImg mask and add compImg.
|
// Blit the pcbImg using the outlineImg mask and add compImg.
|
||||||
// We cannot use PNG.bitblt() for that
|
// We cannot use PNG.bitblt() for that
|
||||||
for (var y = 0; y < boardImg.height; y++) {
|
for (var y = 0; y < boardImg.height; y++) {
|
||||||
|
|
|
@ -27,24 +27,31 @@ try {
|
||||||
var compImgFile = args[1];
|
var compImgFile = args[1];
|
||||||
var dpi = parseFloat(args[2]);
|
var dpi = parseFloat(args[2]);
|
||||||
|
|
||||||
console.log("* Starting Puppeteer (" + vrmlFile + " dpi=" + dpi + "...");
|
console.log("* Starting Puppeteer (" + vrmlFile + " dpi=" + dpi + ")...");
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
const browser = await puppeteer.launch();
|
const browser = await puppeteer.launch({
|
||||||
|
timeout: 60000,
|
||||||
|
slowMo: 500,
|
||||||
|
headless: true,
|
||||||
|
args: ['--unlimited-storage', '--full-memory-crash-report']
|
||||||
|
});
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
|
|
||||||
var contentHtml = fs.readFileSync("bin/render_vrml/render_vrml.html", "utf8");
|
var contentHtml = fs.readFileSync("bin/render_vrml/render_vrml.html", "utf8");
|
||||||
|
|
||||||
console.log("* Reading the input file...");
|
console.log("* Reading the input file...");
|
||||||
var vrmlData = fs.readFileSync(vrmlFile);
|
var vrmlData = fs.readFileSync(vrmlFile);
|
||||||
|
var vrmlDataType = "octet-stream";
|
||||||
if (vrmlFile.endsWith('.gz')) {
|
if (vrmlFile.endsWith('.gz')) {
|
||||||
vrmlData = zlib.gunzipSync(vrmlData);
|
// we unzip it later, on the frontend side
|
||||||
|
vrmlDataType = "x-gzip";
|
||||||
}
|
}
|
||||||
var vrmlDataBase64 = vrmlData.toString("base64");
|
var vrmlDataBase64 = vrmlData.toString("base64");
|
||||||
|
|
||||||
// injecting the data to the client script
|
// injecting the data to the client script
|
||||||
contentHtml = contentHtml.replace("___SCREEN_DPI___", dpi);
|
contentHtml = contentHtml.replace("___SCREEN_DPI___", dpi);
|
||||||
contentHtml = contentHtml.replace("___VRML_DATA___", "data:application/gzip;base64," + vrmlDataBase64);
|
contentHtml = contentHtml.replace("___VRML_DATA___", "data:application/" + vrmlDataType + ";base64," + vrmlDataBase64);
|
||||||
|
|
||||||
page.on("console", message => {
|
page.on("console", message => {
|
||||||
message.args().forEach(async (arg) => {
|
message.args().forEach(async (arg) => {
|
||||||
|
@ -59,12 +66,19 @@ try {
|
||||||
})
|
})
|
||||||
.on("pageerror", ({ message }) => console.log(`* LOG_ERROR: ` + message))
|
.on("pageerror", ({ message }) => console.log(`* LOG_ERROR: ` + message))
|
||||||
.on("response", response => console.log(`* Loading: ` + `${response.status()} ${response.url()}`))
|
.on("response", response => console.log(`* Loading: ` + `${response.status()} ${response.url()}`))
|
||||||
.on("requestfailed", request => console.log(`* Loading Failed: ` + `${request.failure().errorText} ${request.url()}`));
|
.on("requestfailed", request => console.log(`* Loading Failed: ` + `${request.failure() ? request.failure().errorText : "?"} ${request.url()}`));
|
||||||
|
|
||||||
console.log("* Executing the script...");
|
process.on('unhandledRejection', (reason, p) => {
|
||||||
await page.setContent(contentHtml);
|
console.error('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||||
|
browser.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.setDefaultNavigationTimeout(90000); // 90 seconds
|
||||||
|
|
||||||
|
console.log("* Executing the script (content size is " + contentHtml.length + " bytes)...");
|
||||||
|
await page.setContent(contentHtml, { waitUntil: 'domcontentloaded' });
|
||||||
console.log("* Waiting for completion...");
|
console.log("* Waiting for completion...");
|
||||||
const watchDog = page.waitForFunction("document.done");
|
const watchDog = page.waitForFunction("document.done", {timeout: 180000}); // 180 seconds
|
||||||
await watchDog;
|
await watchDog;
|
||||||
|
|
||||||
var screenWidth = await page.evaluate(() => document.compImgWidth);
|
var screenWidth = await page.evaluate(() => document.compImgWidth);
|
||||||
|
@ -72,6 +86,7 @@ try {
|
||||||
console.log("* Saving the screenshot (" + screenWidth + "x" + screenHeight + ")");
|
console.log("* Saving the screenshot (" + screenWidth + "x" + screenHeight + ")");
|
||||||
await page.setViewport({width: screenWidth, height: screenHeight, deviceScaleFactor: 1, });
|
await page.setViewport({width: screenWidth, height: screenHeight, deviceScaleFactor: 1, });
|
||||||
await page.screenshot({path: compImgFile, omitBackground: true});
|
await page.screenshot({path: compImgFile, omitBackground: true});
|
||||||
|
await page.close();
|
||||||
await browser.close();
|
await browser.close();
|
||||||
console.log("* Done! Exiting...");
|
console.log("* Done! Exiting...");
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -21,12 +21,16 @@ var dist = 100;
|
||||||
var minDist = 0.001;
|
var minDist = 0.001;
|
||||||
|
|
||||||
// the far clipping plane is intentionally set to be less than the dist - to clip the board surface!
|
// the far clipping plane is intentionally set to be less than the dist - to clip the board surface!
|
||||||
var boardSurfaceClippingThreshold = 0.0001;
|
var boardSurfaceClippingThreshold = 0.001;
|
||||||
|
|
||||||
|
var gzHeader = "data:application/x-gzip;base64,";
|
||||||
|
|
||||||
// use the official Three.js public distribution
|
// use the official Three.js public distribution
|
||||||
import * as THREE from 'https://unpkg.com/three@0.119.0/build/three.module.js';
|
import * as THREE from 'https://unpkg.com/three@0.119.0/build/three.module.js';
|
||||||
import { VRMLLoader } from 'https://unpkg.com/three@0.119.0/examples/jsm/loaders/VRMLLoader.js';
|
import { VRMLLoader } from 'https://unpkg.com/three@0.119.0/examples/jsm/loaders/VRMLLoader.js';
|
||||||
|
|
||||||
|
import * as fflate from 'https://unpkg.com/three@0.128.0/examples/jsm/libs/fflate.module.js';
|
||||||
|
|
||||||
console.log('Starting...');
|
console.log('Starting...');
|
||||||
|
|
||||||
// this var is checked by the parent Node.js script
|
// this var is checked by the parent Node.js script
|
||||||
|
@ -39,6 +43,18 @@ var renderer;
|
||||||
|
|
||||||
function load() {
|
function load() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
|
if (vrmlData.substring(0, gzHeader.length) === gzHeader) {
|
||||||
|
console.log('Decompressing GZip...');
|
||||||
|
vrmlData = vrmlData.substring(gzHeader.length);
|
||||||
|
var vrmlDataBytes = fflate.strToU8(atob(vrmlData), true);
|
||||||
|
var vrmlDataUncompressed = fflate.gunzipSync(vrmlDataBytes);
|
||||||
|
var vrmlDataUncompressedB64 = btoa(fflate.strFromU8(vrmlDataUncompressed));
|
||||||
|
vrmlData = "data:application/octet-stream;base64," + vrmlDataUncompressedB64;
|
||||||
|
console.log('Decompressed ' + vrmlDataUncompressed.length + ' bytes...');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Loading VRML...');
|
||||||
var loader = new VRMLLoader();
|
var loader = new VRMLLoader();
|
||||||
loader.load(vrmlData, function (object) {
|
loader.load(vrmlData, function (object) {
|
||||||
console.log('Scene and camera setup...');
|
console.log('Scene and camera setup...');
|
||||||
|
@ -78,11 +94,10 @@ function load() {
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
console.log('Init renderer...');
|
console.log('Init renderer...');
|
||||||
renderer = new THREE.WebGLRenderer({antialias: true, alpha: true, preserveDrawingBuffer: true});
|
renderer = new THREE.WebGLRenderer({antialias: true, alpha: true, logarithmicDepthBuffer: true, preserveDrawingBuffer: true});
|
||||||
renderer.setClearColor(0x000000, 0);
|
renderer.setClearColor(0x000000, 0);
|
||||||
document.body.appendChild(renderer.domElement);
|
document.body.appendChild(renderer.domElement);
|
||||||
|
|
||||||
console.log('Loading VRML...');
|
|
||||||
await load();
|
await load();
|
||||||
console.log('Exiting script...');
|
console.log('Exiting script...');
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue