Skip to content

Instantly share code, notes, and snippets.

@mario52a
Last active November 19, 2023 10:50
Show Gist options
  • Save mario52a/262317bc7d8555885b0e to your computer and use it in GitHub Desktop.
Save mario52a/262317bc7d8555885b0e to your computer and use it in GitHub Desktop.
This small macro allows you to build a project 3D very easily from a bitmap image 256 levels of gray. I hope that this macro will revolutionize the way of thinking the CAD and CNC any image when what can be converted to object 3D without any intervention. Everything becomes possible regardless of the complexity of the image !
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
"""
***************************************************************************
* Copyright (c) 2014 2015 2016 2017 2018 2019 2020 2021 <mario52> *
* *
* This file is a supplement to the FreeCAD CAx development system. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License (GPL) *
* as published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* for detail see the LICENCE text file. *
** **
* Use at your own risk. The author assumes no liability for data loss. *
* It is advised to backup your data frequently. *
* If you do not trust the software do not use it. *
** **
* This software is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* License along with this macro; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
* USA *
***************************************************************************
* WARNING! All changes in this file will be lost and *
* may cause malfunction of the program *
***************************************************************************
"""
#OS: Windows 10 (10.0) #OS: Ubuntu 20.10 (KDE/plasma)
#Word size of OS: 64-bit #Word size of OS: 64-bit
#Word size of FreeCAD: 64-bit #Word size of FreeCAD: 64-bit
#Version: 0.19.23546 (Git) #Version: 0.19.23578 (Git)
#Build type: Release #AppImage Build type: Release
#Branch: master #Branch: master
#Hash: 6b017f9a16b15b0e628c8d874c4058442dee5548 #Hash: 50c3cbf00579dc4941ca743c25720d016b0453ce
#Python version: 3.6.8 #Python version: 3.8.6
#Qt version: 5.12.1 #Qt version: 5.12.5
#Coin version: 4.0.0a #Coin version: 4.0.0 OCC
#OCC version: 7.3.0 #version: 7.4.0
#Locale: French/Mars (fr_MA) #Locale: French/Mars (fr_MA)
#
# pour faire une texture de votre image, l'image doit etre en 256 niveaux de gris (N/B)
# une image de 16 millons de couleurs fait l'objet d'une autre procedure d'affichage
# http://forum.freecadweb.org/viewtopic.php?f=24&t=5893&sid=c5f8d32c22e1d1a883741b70b1fea2dc
# ver 0.7 03/09/2014 PyQt4 and PySide 0.8 16/03/2016 0.9 12/12/2016 0.10 24/12/2016
# ver 0.11 2019/07/03 Py3, ver 0.12 2019/08/04, 0.13 2020/04/17 Layout
# ver 0.13b 2020/12/30 try: time.clock() and time.process_time()
# ver 0.14 2021/01/06 new2 path name process accept point in path file colored caracter xyz add search upgrade
# ver 0.14b 2021/01/ Coordinare and Stretching in TAB for screen 15"; 0.14c add "Gui.SendMsgToActiveView("ViewFit")"
#
__title__ = "FCTexture"
__author__ = "Mario52"
__url__ = "https://www.freecadweb.org/"
__Wiki__ = "https://wiki.freecadweb.org/Macro_Texture"
__version__ = "0.14c"
__date__ = "2021/01/16" #YYYY/MM/DD
#
#
import PySide2
from PySide2 import (QtWidgets, QtCore, QtGui)
from PySide2.QtWidgets import (QWidget, QApplication, QSlider, QGraphicsView, QGraphicsScene, QVBoxLayout, QStyle)
from PySide2.QtGui import *
from PySide2.QtCore import *
#from PySide2.QtGui import (QPainter, QColor, QIcon)
#from PySide2.QtSvg import *
#import PySide2.QtXml
import WebGui
import Draft, Part, FreeCAD, math, PartGui, FreeCADGui, FreeCAD
from math import sqrt, pi, sin, cos, asin
from FreeCAD import Base
Gui = FreeCADGui
import Points
#import ReverseEngineering
import os, time, sys
import os.path
#### Detect version macro ###########################################
global switchVesionMacroSearch#; switchVesionMacroSearch = False
try:
def vesionSearch():
import requests
contentPage = requests.get("https://wiki.freecadweb.org/Macro_" + __title__).text
for i in contentPage.split("\n"): # list page to line
if "ctEven macro-version" in i:
versionDetect = (i.split(">")[1])
if "ctEven macro-date" in i:
dateDetect = (i.split(">")[1])
try:
if (len(versionDetect) != 0) and (len(dateDetect) != 0):
break
except Exception:
None
try:
if (versionDetect == __version__) and (dateDetect == __date__):
None
else:
msg = ("New version availlable : " + "\n" +
str(versionDetect) + ":" + str(dateDetect) + "\n" +
"You can install with AddonManager")
FreeCAD.Console.PrintMessage("your actual version : " + str(__version__) + " : " + str(__date__) + "\n")
FreeCAD.Console.PrintMessage("new version availlable : " + str(versionDetect) + " : " + str(dateDetect) + "\n")
diag = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Information, 'New Version', msg)
diag.setWindowModality(QtCore.Qt.ApplicationModal)
diag.exec_()
except Exception:
None
return versionDetect, dateDetect
switchVesionMacroSearch = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).GetBool("switchVesionMacroSearch")
if switchVesionMacroSearch == 0:
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).SetBool("switchVesionMacroSearch", switchVesionMacroSearch)
if switchVesionMacroSearch == True:
vesionSearch()
except Exception:
FreeCAD.Console.PrintMessage("Failed to establish a connection" + "\n")
#### Detect version macro ###########################################
def errorDialog(msg):
diag = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical,u"Error Message",msg )
diag.setWindowModality(QtCore.Qt.ApplicationModal)
diag.exec_()
global verPython ; verPython = sys.version_info.major
def decobit(b0 = 0, b1 = 0, b2 = 0, b3 = 0):
global verPython
if verPython < 3: # Python < 3
b0 = ord(b0)
b1 = ord(b1)
if b2 == 0:
return b0 + (b1*256)
else:
b2 = ord(b2)
b3 = ord(b3)
return b0 + (b1*256) + (b2*65536) + (b3*16777216)
else: # Python > 3
b0 = int(ord(chr(b0)))
b1 = int(ord(chr(b1)))
if b2 == 0:
return b0 + (b1*256)
else:
b2 = int(ord(chr(b2)))
b3 = int(ord(chr(b3)))
return b0 + (b1*256) + (b2*65536) + (b3*16777216)
#### Configuration ###########################################
global SingleStep ; SingleStep = 1.0
#### Configuration ###########################################
global position_X ; position_X = 0.0
global position_Y ; position_Y = 0.0
global position_Z ; position_Z = 0.0
global etirement_X ; etirement_X = 1.0
global etirement_Y ; etirement_Y = 1.0
global etirement_Z ; etirement_Z = 1.0
global modeBrut ; modeBrut = 0
global modeColor ; modeColor = 0
global ecreter ; ecreter = 20
global avecLigne ; avecLigne = 1
global typeligne ; typeligne = 0
global nuance ; nuance = 0
global inversion_X ; inversion_X = 0
global inversion_Y ; inversion_Y = 0
global inversion_Z ; inversion_Z = 0
global plan ; plan = 0
global fond ; fond = 0
global bits_pixel ; bits_pixel = 0
global tailleDonnees; tailleDonnees= 0
global fileCoordasc ; fileCoordasc = 0
global fileCoordpcd ; fileCoordpcd = 0
global ecreterFond ; ecreterFond = 0
global switchContour; switchContour= 0
global valueFilter ; valueFilter = 0
#
global pathFile ; pathFile = ""
global path
#path = FreeCAD.ConfigGet("AppHomePath")
#path = FreeCAD.ConfigGet("UserAppData")
#path = "your path"
param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")# macro path
path = param.GetString("MacroPath","") + "/" # macro path
path = path.replace("\\","/")
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
class Ui_MainWindow(object):
def __init__(self, MainWindow):
self.window = MainWindow
global path
global pathFile
global position_X
global position_Y
global position_Z
global etirement_X
global etirement_Y
global etirement_Z
global modeBrut
global modeColor
global ecreter
global typeligne
global nuance
global avecLigne
global inversion_X
global inversion_Y
global inversion_Z
global plan
global fond
global bits_pixel
global tailleDonnees
global valueFilter
global SingleStep
MainWindow.setObjectName(_fromUtf8(__title__))
# MainWindow.resize(300, 600)
# MainWindow.setMinimumSize(QtCore.QSize(241, 624))
# MainWindow.setMaximumSize(QtCore.QSize(241, 624))
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.groupBox = QtWidgets.QGroupBox()
self.groupBox_01 = QtWidgets.QWidget()
self.LB_01_Coor_X = QtWidgets.QLabel()
self.DS_01_Coor_X = QtWidgets.QDoubleSpinBox()
self.DS_01_Coor_X.setDecimals(7)
self.DS_01_Coor_X.setMinimum(-9999999.0)
self.DS_01_Coor_X.setMaximum(9999999.99)
self.DS_01_Coor_X.setSingleStep(SingleStep)
self.DS_01_Coor_X.setSuffix(u" mm")
self.DS_01_Coor_X.valueChanged.connect(self.on_DS_01_Coor_X_valueChanged)
self.LB_02_Coor_Y = QtWidgets.QLabel()
self.DS_02_Coor_Y = QtWidgets.QDoubleSpinBox()
self.DS_02_Coor_Y.setDecimals(7)
self.DS_02_Coor_Y.setMinimum(-9999999.0)
self.DS_02_Coor_Y.setMaximum(9999999.99)
self.DS_02_Coor_Y.setSingleStep(SingleStep)
self.DS_02_Coor_Y.setSuffix(" mm")
self.DS_02_Coor_Y.valueChanged.connect(self.on_DS_02_Coor_Y_valueChanged)
self.LB_03_Coor_Z = QtWidgets.QLabel()
self.DS_03_Coor_Z = QtWidgets.QDoubleSpinBox()
self.DS_03_Coor_Z.setDecimals(7)
self.DS_03_Coor_Z.setMinimum(-9999999.0)
self.DS_03_Coor_Z.setMaximum(9999999.99)
self.DS_03_Coor_Z.setSingleStep(SingleStep)
self.DS_03_Coor_Z.setSuffix(u" mm")
self.DS_03_Coor_Z.valueChanged.connect(self.on_DS_03_Coor_Z_valueChanged)
####
self.groupBox_02 = QtWidgets.QWidget()
self.LB_01_Stretch_X = QtWidgets.QLabel()
self.DS_01_Stretch_X = QtWidgets.QDoubleSpinBox()
self.DS_01_Stretch_X.setDecimals(7)
self.DS_01_Stretch_X.setMinimum(-9999999.0)
self.DS_01_Stretch_X.setMaximum(9999999.99)
self.DS_01_Stretch_X.setSingleStep(SingleStep)
self.DS_01_Stretch_X.setSuffix(u" mm")
self.DS_01_Stretch_X.valueChanged.connect(self.on_DS_01_Stretch_X_valueChanged)
self.LB_02_Stretch_Y = QtWidgets.QLabel()
self.DS_02_Stretch_Y = QtWidgets.QDoubleSpinBox()
self.DS_02_Stretch_Y.setDecimals(7)
self.DS_02_Stretch_Y.setMinimum(-9999999.0)
self.DS_02_Stretch_Y.setMaximum(9999999.99)
self.DS_02_Stretch_Y.setSingleStep(SingleStep)
self.DS_02_Stretch_Y.setSuffix(u" mm")
self.DS_02_Stretch_Y.valueChanged.connect(self.on_DS_02_Stretch_Y_valueChanged)
self.LB_03_Stretch_Z = QtWidgets.QLabel()
self.DS_03_Stretch_Z = QtWidgets.QDoubleSpinBox()
self.DS_03_Stretch_Z.setDecimals(7)
self.DS_03_Stretch_Z.setMinimum(-9999999.0)
self.DS_03_Stretch_Z.setMaximum(9999999.99)
self.DS_03_Stretch_Z.setSingleStep(SingleStep)
self.DS_03_Stretch_Z.setSuffix(u" mm")
self.DS_03_Stretch_Z.valueChanged.connect(self.on_DS_03_Stretch_Z_valueChanged)
####
self.groupBox_03 = QtWidgets.QGroupBox()
self.CB_01_Axis_X = QtWidgets.QCheckBox()
self.CB_01_Axis_X.clicked.connect(self.on_CB_01_Axis_X_clicked)
self.CB_02_Axis_Y = QtWidgets.QCheckBox()
self.CB_02_Axis_Y.clicked.connect(self.on_CB_02_Axis_Y_clicked)
self.CB_03_Axis_Z = QtWidgets.QCheckBox()
self.CB_03_Axis_Z.clicked.connect(self.on_CB_03_Axis_Z_clicked)
####
self.groupBox_04 = QtWidgets.QGroupBox()
self.RB_01_Wire = QtWidgets.QRadioButton()
self.RB_01_Wire.setChecked(True)
self.RB_01_Wire.setIcon(QtGui.QIcon.fromTheme("Draft",QtGui.QIcon(":/icons/Draft_Wire.svg")))
self.RB_01_Wire.clicked.connect(self.on_RB_01_Wire_clicked)
self.RB_02_BSpline = QtWidgets.QRadioButton()
self.RB_02_BSpline.setIcon(QtGui.QIcon.fromTheme("Draft",QtGui.QIcon(":/icons/Draft_BSpline.svg")))
self.RB_02_BSpline.clicked.connect(self.on_RB_02_BSpline_clicked)
self.RB_03_PointsCloud = QtWidgets.QRadioButton()
self.RB_03_PointsCloud.setIcon(QtGui.QIcon.fromTheme("Draft",QtGui.QIcon(":/icons/PointsWorkbench.svg")))
self.RB_03_PointsCloud.clicked.connect(self.on_RB_03_PointsCloud_clicked)
self.RB_04_Points = QtWidgets.QRadioButton()
self.RB_04_Points.setIcon(QtGui.QIcon.fromTheme("Draft",QtGui.QIcon(":/icons/Draft_Point.svg")))
self.RB_04_Points.clicked.connect(self.on_RB_04_Points_clicked)
self.CB_01_Nuance = QtWidgets.QCheckBox()
self.CB_01_Nuance.setEnabled(False)
self.CB_01_Nuance.clicked.connect(self.on_CB_01_Nuance_clicked)
####
self.groupBox_05 = QtWidgets.QGroupBox()
self.RB_01_Photo = QtWidgets.QRadioButton()
self.RB_01_Photo.setChecked(True)
self.RB_01_Photo.clicked.connect(self.on_RB_01_Photo_clicked)
self.RB_02_PLan = QtWidgets.QRadioButton()
self.RB_02_PLan.clicked.connect(self.on_RB_02_PLan_clicked)
####
self.groupBox_06 = QtWidgets.QGroupBox()
self.CB_01_Pcd = QtWidgets.QCheckBox()
self.CB_01_Pcd.clicked.connect(self.on_CB_01_Pcd_clicked)
self.CB_02_Asc = QtWidgets.QCheckBox()
self.CB_02_Asc.clicked.connect(self.on_CB_02_Asc_clicked)
####
self.groupBox_07 = QtWidgets.QGroupBox()
# section horizontalSlider
self.horizontalSlider = QtWidgets.QSlider()
self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
self.horizontalSlider.setMaximum(255)
self.horizontalSlider.setMinimum(0)
self.horizontalSlider.setSliderPosition(0)
self.horizontalSlider.setPageStep(1)
self.horizontalSlider.setInvertedAppearance(False)
self.horizontalSlider.valueChanged.connect(self.on_horizontal_slider)
self.SP_01_Height = QtWidgets.QSpinBox()
self.SP_01_Height.setMinimum(0)
self.SP_01_Height.setMaximum(255)
self.SP_01_Height.setValue(0)
self.SP_01_Height.setSuffix(u" height")
self.SP_01_Height.valueChanged.connect(self.on_SP_01_Height_valueChanged)
self.LB_01_Mode_Raw = QtWidgets.QLabel()
self.CB_01_Mode_Raw = QtWidgets.QCheckBox()
self.CB_01_Mode_Raw.setAutoFillBackground(False)
self.CB_01_Mode_Raw.clicked.connect(self.on_CB_01_Mode_Raw_clicked)
self.CB_02_Contour = QtWidgets.QCheckBox()
self.CB_02_Contour.clicked.connect(self.on_CB_02_Contour_clicked)
self.SP_02_Contour = QtWidgets.QSpinBox()
self.SP_02_Contour.setMinimum(0)
self.SP_02_Contour.setMaximum(20)
self.SP_02_Contour.setEnabled(False)
self.SP_02_Contour.setValue(0)
self.SP_02_Contour.setSuffix(u"/2 Contour")
self.SP_02_Contour.valueChanged.connect(self.on_SP_02_Contour_valueChanged)
self.LB_03_Capping = QtWidgets.QLabel()
self.CB_03_White = QtWidgets.QCheckBox()
self.CB_03_White.clicked.connect(self.on_CB_03_White_clicked)
self.SP_03_Capping = QtWidgets.QSpinBox()
self.SP_03_Capping.setMinimum(0)
self.SP_03_Capping.setMaximum(20)
self.SP_03_Capping.setValue(20)
self.SP_03_Capping.setSuffix(u" Capping")
self.SP_03_Capping.valueChanged.connect(self.on_SP_03_Capping_valueChanged)
####
self.groupBox_08 = QtWidgets.QGroupBox()
self.LB_01_File = QtWidgets.QLabel()
self.PBA_progressBar = QtWidgets.QProgressBar()
self.PBA_progressBar.setValue(0)
self.PBA_progressBar.setVisible(True)
self.PBA_progressBar.setOrientation(QtCore.Qt.Horizontal)
self.PBA_progressBar.setAlignment(QtCore.Qt.AlignCenter)
self.PB_01_File_Launch = QtWidgets.QPushButton()
self.PB_01_File_Launch.setIcon(QIcon(QApplication.style().standardIcon(QStyle.SP_DialogOkButton)))
self.PB_01_File_Launch.clicked.connect(self.on_PB_01_File_Launch_clicked) # load file
self.PB_02_Help = QtWidgets.QPushButton()
self.PB_02_Help.setIcon(QIcon(QApplication.style().standardIcon(QStyle.SP_MessageBoxQuestion)))
self.PB_02_Help.clicked.connect(self.on_PB_02_Help_clicked) # help
self.PB_03_Quit = QtWidgets.QPushButton()
self.PB_03_Quit.setIcon(QIcon(QApplication.style().standardIcon(QStyle.SP_DialogCloseButton)))
self.PB_03_Quit.clicked.connect(self.on_PB_03_Quit_clicked) # quit
#### layout ###################################################
self.gridLayout_000 = QtWidgets.QGridLayout(self.centralWidget)
self.gridLayout_000.setContentsMargins(10, 10, 10, 10)
self.gridLayout_00 = QtWidgets.QGridLayout(self.groupBox)
self.gridLayout_00.setContentsMargins(10, 10, 10, 10)
####
self.tabWidget = QtWidgets.QTabWidget() #Tab
####
self.tabWidget.addTab(self.groupBox_01, "Coordinate")
self.gridLayout_01 = QtWidgets.QGridLayout(self.groupBox_01)
self.gridLayout_01.setContentsMargins(10, 10, 10, 10)
self.gridLayout_01.addWidget(self.LB_01_Coor_X, 0, 0, 1, 1)
self.gridLayout_01.addWidget(self.DS_01_Coor_X, 0, 1, 1, 1)
self.gridLayout_01.addWidget(self.LB_02_Coor_Y, 1, 0, 1, 1)
self.gridLayout_01.addWidget(self.DS_02_Coor_Y, 1, 1, 1, 1)
self.gridLayout_01.addWidget(self.LB_03_Coor_Z, 2, 0, 1, 1)
self.gridLayout_01.addWidget(self.DS_03_Coor_Z, 2, 1, 1, 1)
####
self.tabWidget.addTab(self.groupBox_02, "Stretching")
self.gridLayout_02 = QtWidgets.QGridLayout(self.groupBox_02)
self.gridLayout_02.setContentsMargins(10, 10, 10, 10)
self.gridLayout_02.addWidget(self.LB_01_Stretch_X, 0, 0, 1, 1)
self.gridLayout_02.addWidget(self.DS_01_Stretch_X, 0, 1, 1, 1)
self.gridLayout_02.addWidget(self.LB_02_Stretch_Y, 1, 0, 1, 1)
self.gridLayout_02.addWidget(self.DS_02_Stretch_Y, 1, 1, 1, 1)
self.gridLayout_02.addWidget(self.LB_03_Stretch_Z, 2, 0, 1, 1)
self.gridLayout_02.addWidget(self.DS_03_Stretch_Z, 2, 1, 1, 1)
####
self.gridLayout_00.addWidget(self.tabWidget, 0, 0, 1, 2)
####
self.gridLayout_03 = QtWidgets.QGridLayout(self.groupBox_03)
self.gridLayout_03.setContentsMargins(10, 10, 10, 10)
self.gridLayout_03.addWidget(self.CB_01_Axis_X, 0, 0, 1, 1)
self.gridLayout_03.addWidget(self.CB_02_Axis_Y, 0, 1, 1, 1)
self.gridLayout_03.addWidget(self.CB_03_Axis_Z, 0, 2, 1, 1)
self.gridLayout_00.addWidget(self.groupBox_03, 2, 0, 1, 2)
####
self.gridLayout_04 = QtWidgets.QGridLayout(self.groupBox_04)
self.gridLayout_04.setContentsMargins(10, 10, 10, 10)
self.gridLayout_04.addWidget(self.RB_01_Wire, 0, 0, 1, 1)
self.gridLayout_04.addWidget(self.RB_02_BSpline, 0, 1, 1, 1)
self.gridLayout_04.addWidget(self.RB_03_PointsCloud, 0, 2, 1, 1)
self.gridLayout_04.addWidget(self.RB_04_Points, 1, 0, 1, 1)
self.gridLayout_04.addWidget(self.CB_01_Nuance, 1, 1, 1, 1)
self.gridLayout_00.addWidget(self.groupBox_04, 3, 0, 1, 2)
####
self.gridLayout_05 = QtWidgets.QGridLayout(self.groupBox_05)
self.gridLayout_05.setContentsMargins(10, 10, 10, 10)
self.gridLayout_05.addWidget(self.RB_01_Photo, 0, 0, 1, 1)
self.gridLayout_05.addWidget(self.RB_02_PLan, 0, 1, 1, 1)
self.gridLayout_00.addWidget(self.groupBox_05, 4, 0, 1, 1)
##
self.gridLayout_06 = QtWidgets.QGridLayout(self.groupBox_06)
self.gridLayout_06.setContentsMargins(10, 10, 10, 10)
self.gridLayout_06.addWidget(self.CB_01_Pcd, 0, 0, 1, 1)
self.gridLayout_06.addWidget(self.CB_02_Asc, 0, 1, 1, 1)
self.gridLayout_00.addWidget(self.groupBox_06, 4, 1, 1, 1)
####
self.gridLayout_07 = QtWidgets.QGridLayout(self.groupBox_07)
self.gridLayout_07.setContentsMargins(10, 10, 10, 10)
self.gridLayout_07.addWidget(self.horizontalSlider, 0, 0, 1, 3)
self.gridLayout_07.addWidget(self.SP_01_Height, 0, 3, 1, 1)
self.gridLayout_07.addWidget(self.LB_01_Mode_Raw, 1, 0, 1, 1)
self.gridLayout_07.addWidget(self.CB_01_Mode_Raw, 1, 1, 1, 1)
self.gridLayout_07.addWidget(self.CB_02_Contour, 1, 2, 1, 1)
self.gridLayout_07.addWidget(self.SP_02_Contour, 1, 3, 1, 1)
self.gridLayout_07.addWidget(self.LB_03_Capping, 2, 0, 1, 1)
self.gridLayout_07.addWidget(self.CB_03_White, 2, 1, 1, 1)
self.gridLayout_07.addWidget(self.SP_03_Capping, 2, 3, 1, 1)
self.gridLayout_00.addWidget(self.groupBox_07, 5, 0, 1, 2)
####
self.gridLayout_08 = QtWidgets.QGridLayout(self.groupBox_08)
self.gridLayout_08.setContentsMargins(10, 10, 10, 10)
self.gridLayout_08.addWidget(self.LB_01_File, 0, 0, 1, 3)
self.gridLayout_08.addWidget(self.PBA_progressBar, 1, 0, 1, 3)
self.gridLayout_08.addWidget(self.PB_01_File_Launch, 2, 0, 1, 1)
self.gridLayout_08.addWidget(self.PB_02_Help, 2, 1, 1, 1)
self.gridLayout_08.addWidget(self.PB_03_Quit, 2, 2, 1, 1)
self.gridLayout_00.addWidget(self.groupBox_08, 6, 0, 1, 2)
self.gridLayout_000.addWidget(self.groupBox, 0, 0, 1, 1)
#### layout ###################################################
MainWindow.setCentralWidget(self.centralWidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(u"FCTexture")
MainWindow.setWindowIcon(QtGui.QIcon(path+'FCTexture.png'))
MainWindow.setWindowFlags(PySide2.QtCore.Qt.WindowStaysOnTopHint) # PySide2 cette fonction met la fenetre en avant
self.groupBox.setTitle(u"ver : " + __version__ + " : " + __date__ + " (rmu)")
####
self.DS_01_Coor_X.setToolTip(u"Coordinate placement Axis X.")
self.LB_01_Coor_X.setText(u"Coordinate <font color=""#a40000""> <b> X </b> </font> <img src=:/icons/Std_CoordinateSystem.svg height=""18"" width=""18"" align=top>")#middle bottom
self.DS_02_Coor_Y.setToolTip(u"Coordinate placement Axis Y.")
self.LB_02_Coor_Y.setText(u"Coordinate <font color=""#4e9a06""> <b> Y </b> </font> <img src=:/icons/Std_CoordinateSystem.svg height=""18"" width=""18"" align=top>")#middle bottom
self.DS_03_Coor_Z.setToolTip(u"Coordinate placement Axis Z.")
self.LB_03_Coor_Z.setText(u"Coordinate <font color=""#204a87""> <b> Z </b> </font> <img src=:/icons/Std_CoordinateSystem.svg height=""18"" width=""18"" align=top>")#middle bottom
####
self.DS_01_Stretch_X.setToolTip(u"Stretching Axis X.")
self.LB_01_Stretch_X.setText(u"<html> <body> Stretching <font color=""#a40000""> <b> X </b> </font> </body> </html>" )
self.DS_02_Stretch_Y.setToolTip(u"Stretching Axis Y.")
self.LB_02_Stretch_Y.setText(u"<html> <body> Stretching <font color=""#4e9a06""> <b> Y </b> </font> </body> </html>" )
self.DS_03_Stretch_Z.setToolTip(u"Stretching Axis Z.")
self.LB_03_Stretch_Z.setText(u"<html> <body> Stretching <font color=""#204a87""> <b> Z </b> </font> </body> </html>" )
####
self.groupBox_03.setTitle(u"Inversion")
self.CB_01_Axis_X.setText(u"Axis X")
self.CB_01_Axis_X.setToolTip(u"Axis X")
self.CB_01_Axis_X.setStyleSheet("color : #a40000; font: bold") # couleur du texte et gras
self.CB_02_Axis_Y.setText(u"Axis Y")
self.CB_02_Axis_Y.setToolTip(u"Axis Y")
self.CB_02_Axis_Y.setStyleSheet("color : #4e9a06; font: bold") # couleur du texte et gras
self.CB_03_Axis_Z.setText(u"Axis Z")
self.CB_03_Axis_Z.setToolTip(u"Axis Z")
self.CB_03_Axis_Z.setStyleSheet("color : #204a87; font: bold") # couleur du texte et gras
####
self.groupBox_04.setTitle(u"Mode 8 Bits")
self.RB_01_Wire.setText(u"Wire")
self.RB_01_Wire.setToolTip(u"Make a Wire")
self.RB_02_BSpline.setText(u"BSpline")
self.RB_02_BSpline.setToolTip(u"Make a BSpline")
self.RB_03_PointsCloud.setToolTip(u"Make a Cloud points")
self.RB_03_PointsCloud.setText(u"Cloud")
self.RB_04_Points.setText(u"Point")
self.RB_04_Points.setToolTip(u"Make a Point (the procedure can be long)")
self.CB_01_Nuance.setText(u"Nuance")
self.CB_01_Nuance.setToolTip(u"To display items in mode photo with shade of gray 20 or 256 shades of gray if Raw mode is set 255")
####
self.groupBox_05.setTitle(u"Mode 32 bits")
self.RB_01_Photo.setText(u"Photo")
self.RB_01_Photo.setToolTip(u"The photo mode is automatically activated when a 32-bit image is detected." + "\n"
u"(the procedure can be long)")
self.RB_02_PLan.setText(u"Plan")
self.RB_02_PLan.setToolTip(u"The plan mode is possible when a 32-bit image and ignore the background of the plan." + "\n"
u"(the procedure can be long)")
##
self.groupBox_06.setTitle(u"File")
self.CB_01_Pcd.setText(u".pcd")
self.CB_01_Pcd.setToolTip(u"Save the coordinates in file format OriginalName.bmp.pcd" + "\n"
u"The function Contour in not availlable with this pcd format" + "\n"
u""
u"Version saved : ascii .PCD v0.7")
self.CB_02_Asc.setText(u".asc")
self.CB_02_Asc.setToolTip(u"Save the coordinates in a file OriginalName.bmp.asc" + "\n"
u"The are in format : X Y Z without comma")
####
self.groupBox_07.setTitle(u"Capping (10 mm)")
self.groupBox_07.setToolTip(u"This function work only with the W/B mode" + "\n"
u"The title group give the real height of the shape" + "\n"
u"Ex: Capping (10 mm)")
self.LB_01_Mode_Raw.setText(u"Raw mode")
self.horizontalSlider.setToolTip(u"This function work only with mode Raw 20" + "\n"
u"The title group give the real height of the shape" + "\n"
u"Ex: 1 to 255")
self.CB_01_Mode_Raw.setText("20")
self.CB_01_Mode_Raw.setToolTip(u"Raw mode 256 colors or 20 colors")
self.LB_03_Capping.setText(u"Capping")
self.SP_01_Height.setToolTip(u"This function work only with mode Raw 20" + "\n"
u"The title group give the real height of the shape" + "\n"
u"Ex: 1 to 255")
self.CB_03_White.setText(u"White")
self.CB_03_White.setToolTip(u"Capping color White or Black")
self.CB_02_Contour.setToolTip(u"Check for activate the Contour SP_03_Capping")
self.SP_02_Contour.setToolTip(u"Contour /2 = 1 mm /2 on the height axis Z")
self.SP_03_Capping.setToolTip(u"Capping [20 to 0 (white) normal mode] or [255 to 0 (white) Raw mode]")
####
self.groupBox_08.setTitle(u"Command")
self.LB_01_File.setText(u"File : ")
self.LB_01_File.setToolTip(u"Gives informations about the file (Bits_pixel, Size data, Length, Height)")
# self.PBA_progressBar.setToolTip(_translate("MainWindow", " ", None))
self.PB_01_File_Launch.setText(u"File and launch")
self.PB_01_File_Launch.setToolTip(u"Load the file and launch the process")
self.PB_02_Help.setText(u"Help")
self.PB_02_Help.setStyleSheet("QToolTip { color: #ffffff; background-color: #204a87; border-color: #ffffff; border-width:2px; border-style:solid; border-radius:0px }");
self.PB_02_Help.setToolTip(u"Display the Wiki page in the FreeCAD browser" + "\n\n"
u"For change the parameter disponible: go to Tools > Edit parameter..." + "\n\n"
u"__The global step on spinBox :__" + "\n"
u"User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__ + " > SingleStep" + "\n"
u"Adjust the value desired (1.0 by default)" + "\n\n"
u"__For search if the macro is upraded :__" + "\n"
u"User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__ + " > switchVesionMacroSearch" + "\n"
u"Adjust the switchVesionMacroSearch to True (False by default)" + "\n")
self.PB_03_Quit.setText(u"Quit")
self.PB_03_Quit.setToolTip(u"Quit FCTexture")
def on_DS_01_Coor_X_valueChanged(self,value):
global position_X
position_X = value
def on_DS_02_Coor_Y_valueChanged(self,value):
global position_Y
position_Y = value
def on_DS_03_Coor_Z_valueChanged(self,value):
global position_Z
position_Z = value
def on_DS_01_Stretch_X_valueChanged(self,value):
global etirement_X
etirement_X = value
def on_DS_02_Stretch_Y_valueChanged(self,value):
global etirement_Y
etirement_Y = value
def on_DS_03_Stretch_Z_valueChanged(self,value):
global etirement_Z
etirement_Z = value
def on_horizontal_slider(self, value):
global modeBrut
global ecreter
global valueFilter
if modeBrut == 0:
valueFilter = float(value)
self.SP_01_Height.setValue(value)
self.groupBox_07.setTitle("Height ("+str(valueFilter)+" mm)")
else:
valueFilter = 0.0
self.horizontalSlider.setSliderPosition(0)
self.SP_01_Height.setValue(0)
def on_SP_01_Height_valueChanged(self, value):
global modeBrut
global ecreter
global valueFilter
if modeBrut == 0:
valueFilter = float(value)
self.horizontalSlider.setValue(value)
self.groupBox_07.setTitle("Height ("+str(valueFilter)+" mm)")
else:
valueFilter = 0.0
self.horizontalSlider.setSliderPosition(0)
self.SP_01_Height.setValue(0)
def on_CB_01_Mode_Raw_clicked(self):
global modeBrut
global ecreter
global valueFilter
valueFilter = 0.0
self.horizontalSlider.setSliderPosition(0)
if self.CB_01_Mode_Raw.isChecked():
modeBrut = 1 # if checked mode brut = 255 colors
self.SP_03_Capping.setMaximum(255)
self.groupBox_07.setTitle("Capping (255 mm)")
self.CB_01_Mode_Raw.setText("255")
self.SP_02_Contour.setMaximum(255)
self.SP_02_Contour.setSuffix(u" Contour")
self.SP_02_Contour.setToolTip(u"Contour = 1 mm on the height axis Z")
self.SP_01_Height.setEnabled(False)
if self.CB_03_White.isChecked(): # if Black
self.SP_03_Capping.setValue(0)
ecreter = 0
else:
self.SP_03_Capping.setValue(255)
ecreter = 255
else:
modeBrut = 0 # if nochecked White mode brut = 20 colors
self.SP_03_Capping.setMaximum(20)
self.groupBox_07.setTitle("Capping (10 mm)")
self.CB_01_Mode_Raw.setText("20")
self.SP_02_Contour.setMaximum(20)
self.SP_02_Contour.setSuffix(u"/2 Contour")
self.SP_02_Contour.setToolTip(u"Contour /2 = 1 mm /2 on the height axis Z")
self.SP_01_Height.setEnabled(True)
if self.CB_03_White.isChecked(): # if Black
self.SP_03_Capping.setValue(0)
ecreter = 0
else:
self.SP_03_Capping.setValue(20) # if White
ecreter = 20
def on_CB_03_White_clicked(self): # if checked ecreter Black else White
global modeColor
global ecreter
global valueFilter
valueFilter = 0.0
self.horizontalSlider.setSliderPosition(0)
if self.CB_03_White.isChecked():
modeColor = 1 # if checked mode Black
self.CB_03_White.setText("Black")
self.SP_03_Capping.setValue(0)
else:
modeColor = 0 # if nochecked mode White
self.CB_03_White.setText("White")
if self.CB_01_Mode_Raw.isChecked():
self.SP_03_Capping.setValue(255)
self.SP_02_Contour.setSuffix(u" Contour")
self.SP_02_Contour.setToolTip(u"Contour = 1 mm on the height axis Z")
else:
self.SP_03_Capping.setValue(20)
self.SP_02_Contour.setSuffix(u"/2 Contour")
self.SP_02_Contour.setToolTip(u"Contour /2 = 1 mm /2 on the height axis Z")
def on_SP_03_Capping_valueChanged(self,value): # ecreter
global ecreter
global valueFilter
valueFilter = 0.0
self.horizontalSlider.setSliderPosition(0)
ecreter = value
def on_CB_02_Contour_clicked(self):
global switchContour
global ecreterFond
global valueFilter
global fileCoordpcd
valueFilter = 0.0
self.horizontalSlider.setSliderPosition(0)
self.CB_01_Pcd.setChecked(False)
fileCoordpcd = 0
if self.CB_02_Contour.isChecked():
switchContour = 1
self.SP_02_Contour.setEnabled(True)
if self.CB_01_Mode_Raw.isChecked():
self.SP_03_Capping.setValue(255)
self.SP_02_Contour.setSuffix(u" Contour")
self.SP_02_Contour.setToolTip(u"Contour = 1 mm on the height axis Z")
else:
self.SP_03_Capping.setValue(20)
self.SP_02_Contour.setSuffix(u"/2 Contour")
self.SP_02_Contour.setToolTip(u"Contour /2 = 1 mm /2 on the height axis Z")
else:
switchContour = 0
ecreterFond = 0
self.SP_02_Contour.setValue(0)
self.SP_02_Contour.setEnabled(False)
if self.CB_01_Mode_Raw.isChecked():
self.SP_02_Contour.setSuffix(u" Contour")
self.SP_02_Contour.setToolTip(u"Contour = 1 mm on the height axis Z")
else:
self.SP_02_Contour.setSuffix(u"/2 Contour")
self.SP_02_Contour.setToolTip(u"Contour /2 = 1 mm /2 on the height axis Z")
def on_SP_02_Contour_valueChanged(self,value): # ecreter Fond
global ecreterFond
ecreterFond = value
def on_RB_04_Points_clicked(self): # if checked then mode point N/B
global avecLigne
avecLigne = 0
self.CB_01_Nuance.setEnabled(True)
self.CB_02_Contour.setEnabled(True)
def on_RB_01_Wire_clicked(self): # if checked then 0=makeWire N/B
global typeligne
global avecLigne
typeligne = 0
avecLigne = 1
self.CB_01_Nuance.setChecked(False)
self.CB_01_Nuance.setEnabled(False)
self.CB_02_Contour.setEnabled(True)
def on_RB_02_BSpline_clicked(self): # if no checked then 1=BSpline N/B
global typeligne
global avecLigne
global switchContour
global ecreterFond
typeligne = 1
avecLigne = 1
switchContour = 0
ecreterFond = 0
self.CB_01_Nuance.setChecked(False)
self.CB_01_Nuance.setEnabled(False)
self.CB_02_Contour.setEnabled(False)
self.CB_02_Contour.setChecked(False)
self.SP_02_Contour.setValue(0)
self.SP_02_Contour.setEnabled(False)
if self.CB_01_Mode_Raw.isChecked():
self.SP_02_Contour.setSuffix(u" Contour")
self.SP_02_Contour.setToolTip(u"Contour = 1 mm on the height axis Z")
else:
self.SP_02_Contour.setSuffix(u"/2 Contour")
self.SP_02_Contour.setToolTip(u"Contour /2 = 1 mm /2 on the height axis Z")
def on_RB_03_PointsCloud_clicked(self): # Cloud points
global typeligne
global avecLigne
typeligne = 2
ecreterFond = 0
self.CB_01_Nuance.setChecked(False)
self.CB_01_Nuance.setEnabled(False)
self.CB_02_Contour.setEnabled(True)
def on_CB_01_Axis_X_clicked(self): # if checked inverse X
global inversion_X
if self.CB_01_Axis_X.isChecked():
inversion_X = 1
else:
inversion_X = 0
def on_CB_02_Axis_Y_clicked(self): # if checked inverse Y
global inversion_Y
if self.CB_02_Axis_Y.isChecked():
inversion_Y = 1
else:
inversion_Y = 0
def on_CB_03_Axis_Z_clicked(self): # if checked inverse Z
global inversion_Z
if self.CB_03_Axis_Z.isChecked():
inversion_Z = 1
else:
inversion_Z = 0
def on_RB_01_Photo_clicked(self): # if checked then Photo colors
global plan
plan = 0
def on_RB_02_PLan_clicked(self): # if checked then Plan colors
global plan
global modeBrut
global ecreter
plan = 1
modeBrut = 1 # if checked mode brut = 255 colors
ecreter = 255
self.SP_03_Capping.setMaximum(255)
self.SP_03_Capping.setValue(255)
self.CB_03_White.setText("White")
self.CB_01_Mode_Raw.setText("255")
self.CB_01_Mode_Raw.setChecked(True)
def on_CB_01_Nuance_clicked(self): # if checked fond Black else White
global nuance
if self.CB_01_Nuance.isChecked():
nuance = 1 # if checked Nuance ok
else:
nuance = 0 # if nochecked Nuance Ko
def on_PB_03_Quit_clicked(self):
FreeCAD.Console.PrintMessage("End FCTexture"+"\n")
self.window.hide()
def on_PB_02_Help_clicked(self):
WebGui.openBrowser("https://wiki.freecadweb.org/Macro_FCTexture")
App.Console.PrintMessage("https://wiki.freecadweb.org/Macro_FCTexture" + "\n")
def on_CB_01_Pcd_clicked(self): # pcd
global fileCoordpcd
if self.CB_02_Contour.isChecked():
self.CB_01_Pcd.setChecked(False)
else:
if self.CB_01_Pcd.isChecked():
fileCoordpcd = 1 # if checked file pcd ok
else:
fileCoordpcd = 0 # if nochecked file pcd Ko
def on_CB_02_Asc_clicked(self): # Asc
global fileCoordasc
if self.CB_02_Asc.isChecked():
fileCoordasc = 1 # if checked file asc ok
else:
fileCoordasc = 0 # if nochecked file asc Ko
def on_PB_01_File_Launch_clicked(self):
global path
global pathFile
global position_X
global position_Y
global position_Z
global etirement_X
global etirement_Y
global etirement_Z
global modeBrut
global modeColor
global ecreter
global typeligne
global avecLigne
global inversion_X
global inversion_Y
global inversion_Z
global plan
global fond
global bits_pixel
global tailleDonnees
global fileCoordasc
global fileCoordpcd
global ecreterFond
global switchContour
global valueFilter
# Configuration FCTexture
# FreeCAD.Console.PrintMessage("position_X : "+str(position_X)+"\n")
# FreeCAD.Console.PrintMessage("position_Y : "+str(position_Y)+"\n")
# FreeCAD.Console.PrintMessage("position_Z : "+str(position_Z)+"\n")
# FreeCAD.Console.PrintMessage("etirement_X : "+str(etirement_X)+"\n")
# FreeCAD.Console.PrintMessage("etirement_Y : "+str(etirement_Y)+"\n")
# FreeCAD.Console.PrintMessage("etirement_Z : "+str(etirement_Z)+"\n")
# FreeCAD.Console.PrintMessage("ecreter : "+str(ecreter)+"\n")
# FreeCAD.Console.PrintMessage("wire : "+str(avecLigne)+"\n")
# FreeCAD.Console.PrintMessage("typeligne : "+str(typeligne)+"\n")
# FreeCAD.Console.PrintMessage("point : "+str(avecLigne)+"\n")
# FreeCAD.Console.PrintMessage("inversion_X : "+str(inversion_X)+"\n")
# FreeCAD.Console.PrintMessage("inversion_Y : "+str(inversion_Y)+"\n")
# FreeCAD.Console.PrintMessage("inversion_Z : "+str(inversion_Z)+"\n")
# FreeCAD.Console.PrintMessage("plan : "+str(plan)+"\n")
# FreeCAD.Console.PrintMessage("fond : "+str(fond)+"\n")
doc = FreeCAD.ActiveDocument
if doc == None:
doc = FreeCAD.newDocument()
self.PB_01_File_Launch.setStyleSheet("background-color: QPalette.Base") # origin system
self.LB_01_File.setText("File :")
OpenName = ""
OpenName, Filter = PySide2.QtWidgets.QFileDialog.getOpenFileName(None, "Read an image file", pathFile, "*.bmp")# PySide2
try:
if OpenName != "":
SaveName = OpenName
####new2
pathFile = os.path.dirname(SaveName) + "/" #= C:/Provisoire400/
formatFichier = os.path.splitext(SaveName)[1] #= .png
SaveName = os.path.splitext(SaveName)[0] #= /home/kubuntu/.FreeCAD/Macro/Texture_007_H #= C:/Provisoire400/image3D
SaveNameformatFichier = SaveName + formatFichier #= C:/Provisoire400/image3D.png
####new2
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/FCTexture").SetString("Path",pathFile)
####new
OpenName = SaveNameformatFichier
try:
depart = time.clock()
except Exception:
try:
depart = time.process_time()
except Exception: None
FreeCAD.Console.PrintMessage("Read the file "+OpenName+"\n")
f = open(OpenName, "rb")
length = os.path.getsize(OpenName)
# decode header file
bytes = f.read(2)# Signature du fichier. BM=Bitmap windows, BA= Bitmap
# FreeCAD.Console.PrintMessage(str(bytes[0]) + str(bytes[1])+"\n")
bytes = f.read(4)# Taille totale du fichier en octets
bytes = f.read(4)# Champ reserve
bytes = f.read(4)# Adresse de la zone de definition de l image
adresse = decobit(bytes[0],bytes[1],bytes[2],bytes[3])
# FreeCAD.Console.PrintMessage(str(adresse)+" adresse "+"\n")
bytes = f.read(4)# Taille en octets de l'en-tete BITMAPINFOHEADER
entete = decobit(bytes[0],bytes[1],bytes[2],bytes[3])
# FreeCAD.Console.PrintMessage(str(entete)+" entete "+"\n")
bytes = f.read(4)# Largeur de l image en pixels
Largeur = decobit(bytes[0],bytes[1],bytes[2],bytes[3])
# FreeCAD.Console.PrintMessage(str(Largeur)+" Largeur "+"\n")
bytes = f.read(4)# Hauteur de l image en pixels
hauteur = decobit(bytes[0],bytes[1],bytes[2],bytes[3])
# FreeCAD.Console.PrintMessage(str(hauteur)+" hauteur "+"\n")
bytes = f.read(2)# Nombre de plans
plans = decobit(bytes[0],bytes[1])
# FreeCAD.Console.PrintMessage(str(plans)+" plans "+"\n")
bytes = f.read(2)# Nombre de bits par pixel
bits_pixel = decobit(bytes[0],bytes[1])
FreeCAD.Console.PrintMessage(str(bits_pixel)+" bits_pixel "+"\n")
bytes = f.read(4)# Type de compression : 0=pas de compression,1=compresse a 8 bits par pixel, 2=4bits par pixel.
bytes = f.read(4)# Taille en octets des donnees de l image
tailleDonnees = decobit(bytes[0],bytes[1],bytes[2],bytes[3])
# FreeCAD.Console.PrintMessage(str(tailleDonnees)+" tailleDonnees "+"\n")
bytes = f.read(4)# Resolution horizontale en pixels par metre
bytes = f.read(4)# Resolution verticale en pixels par metre
bytes = f.read(4)# Nombre de couleurs dans l image : 0=maximum possible. Si une palette est utilisee, ce nombre indique le nombre de couleurs de la palette
couleurs = decobit(bytes[0],bytes[1],bytes[2],bytes[3])
# FreeCAD.Console.PrintMessage(str(couleurs)+" couleurs "+"\n")
bytes = f.read(4)# Nombre de couleurs importantes. 0= toutes importantes
self.LB_01_File.setText("File: "+str(bits_pixel)+":bits " +str(tailleDonnees)+":data ("+str(Largeur)+" x "+str(hauteur)+")")
Gui.updateGui() # rafraichi l'ecran
f.seek(adresse, 0) # seek(position, 0=defaut 1=a la position courante 2=a partir de la fin du fichier)
coor_X = 0.0
coor_Y = 0.0
coor_Z = 0.0
###########256 couleurs debut#####################################
if couleurs == 256:
completion = Largeur % 4
ii = 0
pnts = []
points = []
pointsCloud = []
del pnts[:]
del points[:]
del pointsCloud[:]
import Points
pointsCloud = Points.Points()
## contourLineG = [] # ligne du bord gauche
## del contourLineG[:] # ligne du bord gauche
## contourLineD = [] # ligne du bord droit
## del contourLineD[:] # ligne du bord droit
self.PBA_progressBar.setMaximum(tailleDonnees)
for Y in range(tailleDonnees):
self.PBA_progressBar.setValue(Y)
ii += 1
try:
bytes = ord(f.read(1))
pnts.append(str(bytes))
except:
None
try:
if ((ii % Largeur) == 0) and (completion > 0):
if completion == 3:
bytes = (f.read(1))
Y += 1
elif completion == 2:
bytes = (f.read(2))
Y += 2
elif completion == 1:
bytes = (f.read(3))
Y += 3
ii = 0
except:
None
f.close()
ii = 0
####################################################################### pour asc
if fileCoordasc != 0:
mypath = OpenName + ".asc"
file_asc = open(mypath,"w") # save coordinates OpenName.asc
####################################################################### pour pcd
# .PCD v.7 - Point Cloud Data file format # http://pointclouds.org/documentation/tutorials/pcd_file_format.php
# for save PCD format #
if fileCoordpcd != 0:
mypath = OpenName + ".pcd"
file_pcd = open(mypath,"w") # save coordinates OpenName.pcd # pour fichier PCD
file_pcd.write("# .PCD v0.7 - Point Cloud Data file format" + "\n") # .PCD v0.7 - Point Cloud Data file format
file_pcd.write("VERSION .7" + "\n") # VERSION 0.7
file_pcd.write("FIELDS x y z rgb" + "\n") # FIELDS x y z rgb
file_pcd.write("SIZE 4 4 4 4"+"\n") # SIZE 4
file_pcd.write("TYPE F F F F"+"\n") # F F F F
file_pcd.write("COUNT 1 1 1 1"+"\n") # COUNT 1 1 1 1
file_pcd.write("WIDTH " + str(Largeur) + "\n") # WIDTH 640
file_pcd.write("HEIGHT " + str(hauteur) + "\n") # HEIGHT 480
file_pcd.write("VIEWPOINT 0 0 0 1 0 0 0" + "\n") # VIEWPOINT 0 0 0 1 0 0 0
file_pcd.write("POINTS " + str( Largeur * hauteur) + "\n") # POINTS 307200
file_pcd.write("DATA ascii" + "\n") # DATA ascii
####################################################################### pour pcd
if modeBrut == 0:
ecreterFond = self.SP_02_Contour.value()
ecreterFond = (float(ecreterFond)/2)
self.SP_02_Contour.setSuffix(u"/2 Contour")
else:
ecreterFond = self.SP_02_Contour.value()
self.SP_02_Contour.setSuffix(u" Contour")
if switchContour == 0:
ecreterFond = 1000
if self.CB_03_Axis_Z.isChecked():
ecreterFond = (-ecreterFond)
self.PBA_progressBar.setMaximum(hauteur)
for Y in range(hauteur):
self.PBA_progressBar.setValue(Y)
## switchLine = 0 # switch lignes bords gauche droit
for X in range(Largeur):
if X > Largeur:
del points[:]
else:
if modeBrut == 0:
if float(pnts[ii]) > 247: # 20 Filter
pnts[ii] = "10"
elif float(pnts[ii]) > 234: # 19
pnts[ii] = "9.5"
elif float(pnts[ii]) > 221: # 18
pnts[ii] = "9"
elif float(pnts[ii]) > 208: # 17
pnts[ii] = "8.5"
elif float(pnts[ii]) > 195: # 16
pnts[ii] = "8"
elif float(pnts[ii]) > 182: # 15
pnts[ii] = "7.5"
elif float(pnts[ii]) > 169: # 14
pnts[ii] = "7"
elif float(pnts[ii]) > 156: # 13
pnts[ii] = "6.5"
elif float(pnts[ii]) > 143: # 12
pnts[ii] = "6"
elif float(pnts[ii]) > 130: # 11
pnts[ii] = "5.5"
elif float(pnts[ii]) > 117: # 10
pnts[ii] = "5"
elif float(pnts[ii]) > 104: # 9
pnts[ii] = "4.5"
elif float(pnts[ii]) > 91: # 8
pnts[ii] = "4"
elif float(pnts[ii]) > 78: # 7
pnts[ii] = "3.5"
elif float(pnts[ii]) > 65: # 6
pnts[ii] = "3"
elif float(pnts[ii]) > 52: # 5
pnts[ii] = "2.5"
elif float(pnts[ii]) > 39: # 4
pnts[ii] = "2"
elif float(pnts[ii]) > 26: # 3
pnts[ii] = "1.5"
elif float(pnts[ii]) > 13: # 2
pnts[ii] = "1"
elif float(pnts[ii]) > 1: # 1
pnts[ii] = "0.5"
else :
pnts[ii] = "0" # 0
if modeBrut == 0: # ecreter 20 colors
if modeColor == 0:
if float(pnts[ii]) > ((ecreter + 1) / 2): # ecreter White
pnts[ii] = str((ecreter + 1) / 2)
else:
if float(pnts[ii]) < ((ecreter + 1) / 2): # ecreter Black
pnts[ii] = str((ecreter + 1) / 2)
else: # ecreter 255 colors
if modeColor == 0:
if float(pnts[ii]) > ecreter: # ecreter White
pnts[ii] = str(ecreter)
else:
if float(pnts[ii]) < ecreter: # ecreter Black
pnts[ii] = str(ecreter)
if (valueFilter != 0.0) and (modeBrut == 0):
pnts[ii] = str( float(pnts[ii]) * (valueFilter/10.0))
coor_X = (X * etirement_X) + position_X
coor_Y = (Y * etirement_Y) + position_Y
coor_Z = (float(pnts[ii]) * etirement_Z) + position_Z
if inversion_X > 0:
coor_X = (-coor_X)
if inversion_Y > 0:
coor_Y = (-coor_Y)
if inversion_Z > 0:
coor_Z = (-coor_Z)
if (coor_Z != ecreterFond): # ici pour contour
try:
if typeligne == 2: # 2=cloud
pointsCloud.addPoints([FreeCAD.Vector(coor_X,coor_Y,coor_Z)])
points += [FreeCAD.Vector(coor_X,coor_Y,coor_Z)] # (pour remplir)
if avecLigne == 1: # 1=Ligne 0=point 2=cloud
points += [FreeCAD.Vector(coor_X,coor_Y,coor_Z)]
elif avecLigne == 0: # 0=point
if nuance == 1: # 1 = nuance
a = Draft.makePoint(coor_X,coor_Y,coor_Z)
FreeCADGui.activeDocument().getObject(a.Label).PointColor = (coor_Z*0.00392157,coor_Z*0.00392157,coor_Z*0.00392157)
else:
Draft.makePoint(coor_X,coor_Y,coor_Z)
################################################################### pour asc
if fileCoordasc != 0:
file_asc.write(str(coor_X)+" "+str(coor_Y)+" "+str(coor_Z)+"\n")
################################################################### pour pcd
if fileCoordpcd != 0:
pcdColor = 0.0 #(pcdColor_r) + (pcdColor_v*256) + (pcdColor_b*65536) # pour un champ
file_pcd.write(str(coor_X) + " " + str(coor_Y) + " " + str(coor_Z) + " " + str(pcdColor)+"\n") #
################################################################### pour pcd
except:
try:
file_asc.close() # essais if error detected to write ... or not the file is closed
except Exception:
None
FreeCAD.Console.PrintError("Not ActiveDocument detected "+"\n")# errorDialog("Not ActiveDocument detected")
break
elif (len(points) > 0):
if ((avecLigne == 1) and (len(points) != 0)) or (typeligne == 2):
###cree la ligne jusque la base###############################
if points[0].z != 0.0:
points.insert(0,points[0])
points[0].z = 0.0
pointsCloud.addPoints([points[0]])
if points[-1].z != 0.0:
points.append(FreeCAD.Vector(points[-1].x,points[-1].y,points[-1].z))
points[-1].z = 0.0
pointsCloud.addPoints([points[-1]])
###cree la ligne jusque la base###############################
if (points[0] != points[-1]):
if (typeligne == 0): # 0=makeWire
Draft.makeWire(points,closed=False,face=False,support=None)
elif typeligne == 1:
Draft.makeBSpline(points,closed=False) # 1=makeBSpline
## if switchLine == 0: # ligne du bord gauche droit
## switchLine = 1 # ligne du bord gauche droit
## contourLineG.append(points[0]) # ligne du bord gauche
## contourLineD.append(points[-1]) # ligne du bord droit
del points[:]
ii += 1
try:
if (avecLigne == 1) and (len(points) != 0) and (typeligne != 2):
## if switchLine == 0: # ligne du bord gauche droit
## switchLine = 1 # ligne du bord gauche droit
## contourLineG.append(points[0]) # ligne du bord gauche
## contourLineD.append(points[-1]) # ligne du bord droit
if typeligne == 0: # 0=makeWire
Draft.makeWire(points,closed=False,face=False,support=None)
else:
Draft.makeBSpline(points,closed=False) # 1=makeBSpline
except:
FreeCAD.Console.PrintError("Not ActiveDocument detected "+"\n") #errorDialog("Not ActiveDocument detected")
break
del points[:]
## Draft.makeWire(contourLineG,closed=False,face=False,support=None) # ligne du bord gauche
## del contourLineG[:] # ligne du bord gauche
## Draft.makeWire(contourLineD,closed=False,face=False,support=None) # ligne du bord droit
## del contourLineD[:] # ligne du bord droit
if typeligne == 2:
Points.show(pointsCloud)
#### Create nurbs surface#####################################
# import ReverseEngineering as Reen
# create an approximating nurbs surface with smoothing algorithm
# s = Reen.approxSurface(Points=pointsCloud, UDegree=4, VDegree=4, NbUPoles=16, NbVPoles=16, Smooth=True, Weight=0.1, Grad=0.5,Bend=0.2, Iterations=5, Correction=True, PatchFactor=1.2)
# Part.show(s.toShape())
# App.ActiveDocument.recompute()
# create an approximating nurbs surface with smoothing algorithm
# #### Create Mesh #############################################
#http://forum.freecadweb.org/viewtopic.php?f=13&t=12796&start=10
# import ReverseEngineering as Reen
# mesh=Reen.triangulate(pointsCloud, 10000, 8.0)
# import Mesh
# Mesh.show(mesh)
if fileCoordasc != 0:
file_asc.close() # pour asc
if fileCoordpcd != 0:
file_pcd.close() # pour pcd
if (valueFilter != 0.0):
# global ui # appel
ff = ui
ff.on_CB_01_Mode_Raw_clicked()
valueFilter = 0
##256 couleurs fin#####################################
#
###########16 millions couleurs debut###########################
elif bits_pixel == 32: #if couleurs == 0: # 16 millions couleurs pour 32 bits mode 1 bit
if adresse == 138: # mode 2 bits
bytes = (f.read(1))
completion = Largeur % 4
ii = 0
ic = 0
r_color = 0.0
v_color = 0.0
b_color = 0.0
pnts = []
points = []
del pnts[:]
del points[:]
self.PBA_progressBar.setMaximum(tailleDonnees)
for Y in range(tailleDonnees):
self.PBA_progressBar.setValue(Y)
ii = 0
for ic in range(3):
ii += 1
try:
bytes = ord(f.read(1))
pnts.append(str(bytes))
except:
None
f.read(1)
ii += 1
try:
if ((ii % Largeur) == 0) and (completion > 0):
if completion == 3:
bytes = ord(f.read(1))
Y += 1
elif completion == 2:
bytes = ord(f.read(2))
Y += 2
elif completion == 1:
bytes = ord(f.read(3))
Y += 3
except:
None
f.close()
ii = 0
self.PBA_progressBar.setMaximum(hauteur)
if fileCoordasc != 0:
mypath = OpenName + ".asc"
file_asc = open(mypath,"w") # save coordinates OpenName.asc
####################################################################### pour pcd
# .PCD v.7 - Point Cloud Data file format
# for save PCD format #
if fileCoordpcd != 0:
mypath = OpenName + ".pcd"
file_pcd = open(mypath,"w") # save coordinates OpenName.pcd # pour fichier PCD #http://pointclouds.org/documentation/tutorials/pcd_file_format.php
file_pcd.write("# .PCD v0.7 - Point Cloud Data file format" + "\n") # .PCD v0.7 - Point Cloud Data file format
file_pcd.write("VERSION .7" + "\n") # VERSION 0.7
file_pcd.write("FIELDS x y z rgb" + "\n") # FIELDS x y z rgb
file_pcd.write("SIZE 4 4 4 4"+"\n") # SIZE 4
file_pcd.write("TYPE F F F F"+"\n") # F F F F
file_pcd.write("COUNT 1 1 1 1"+"\n") # COUNT 1 1 1 1
file_pcd.write("WIDTH " + str(Largeur) + "\n") # WIDTH 640
file_pcd.write("HEIGHT " + str(hauteur) + "\n") # HEIGHT 480
file_pcd.write("VIEWPOINT 0 0 0 1 0 0 0" + "\n") # VIEWPOINT 0 0 0 1 0 0 0
file_pcd.write("POINTS " + str( Largeur * hauteur) + "\n") # POINTS 307200
file_pcd.write("DATA ascii" + "\n") # DATA ascii
####################################################################### pour pcd
for Y in range(hauteur):
self.PBA_progressBar.setValue(Y)
for X in range(Largeur):
if X > Largeur:
del points[:]
else:
coor_X = (X * etirement_X) + position_X
coor_Y = (Y * etirement_Y) + position_Y
coor_Z = ( etirement_Z) + position_Z
if inversion_X > 0:
coor_X = (-coor_X)
if inversion_Y > 0:
coor_Y = (-coor_Y)
if inversion_Z > 0:
coor_Z = (-coor_Z)
b_color = float(pnts[ii])*0.00392157 ; pcdColor_b = int(pnts[ii])*65536 # a partir du ";" encodage pour PCD
ii += 1
v_color = float(pnts[ii])*0.00392157 ; pcdColor_v = int(pnts[ii])*256 # a partir du ";" encodage pour PCD
ii += 1
r_color = float(pnts[ii])*0.00392157 ; pcdColor_r = int(pnts[ii]) # a partir du ";" encodage pour PCD
ii += 1
try:
if plan == 0: # 0=Photo
a = Draft.makePoint(coor_X,coor_Y,coor_Z) # ok pour 32 bits mode
FreeCADGui.activeDocument().getObject(a.Label).PointColor = (r_color,v_color,b_color)
else: # 1=Plan
if modeColor == 0: # white background
if (r_color < (ecreter*0.00392157)) and (r_color < (ecreter*0.00392157)) and (r_color < (ecreter*0.00392157)): # ecreter White
a = Draft.makePoint(coor_X,coor_Y,coor_Z)
FreeCADGui.activeDocument().getObject(a.Label).PointColor = (r_color,v_color,b_color)
else: # black background
if (r_color > (ecreter*0.00392157)) and (r_color > (ecreter*0.00392157)) and (r_color > (ecreter*0.00392157)): # ecreter Black
a = Draft.makePoint(coor_X,coor_Y,coor_Z)
FreeCADGui.activeDocument().getObject(a.Label).PointColor = (r_color,v_color,b_color)
################################################################### pour asc
if fileCoordasc != 0:
file_asc.write(str(coor_X)+" "+str(coor_Y)+" "+str(coor_Z)+"\n")
################################################################### pour pcd
if fileCoordpcd != 0:
pcdColor = (pcdColor_r) + (pcdColor_v*256) + (pcdColor_b*65536) # pour un champ (pas teste avec FreeCAD)
file_pcd.write(str(coor_X) + " " + str(coor_Y) + " " + str(coor_Z) + " " + str(pcdColor)+"\n") #
################################################################### pour pcd
except:
try:
file_asc.close()
except Exception:
None
FreeCAD.Console.PrintError("Not ActiveDocument detected "+"\n")
break
del points[:]
if fileCoordasc != 0:
try:
file_asc.close() # pour asc
except Exception:
None
if fileCoordpcd != 0:
try:
file_pcd.close() # pour pcd
except Exception:
None
###########16 millions couleurs fin#####################################
else:
FreeCAD.Console.PrintError("Bits_pixel "+str(bits_pixel)+" unrecognized format"+"\n")
FreeCAD.Console.PrintWarning("Wait i recompute :"+"\n")
Gui.updateGui() # rafraichi l'ecran
App.ActiveDocument.recompute()
self.PB_01_File_Launch.setStyleSheet("background-color: green") # This function gives a color button
try:
arrivee = time.clock()
FreeCAD.Console.PrintMessage("Time : "+str("%.2f" % ((arrivee - depart)/60))+" min"+"\n")
except Exception:
try:
arrivee = time.process_time()
FreeCAD.Console.PrintMessage("Time : "+str("%.2f" % ((arrivee - depart)/60))+" min"+"\n")
except Exception: None
Gui.SendMsgToActiveView("ViewFit")
FreeCAD.Console.PrintMessage("_End Work_____________"+"\n")
except:
self.PB_01_File_Launch.setStyleSheet("background-color: red") # This function gives a color button
FreeCAD.Console.PrintMessage("Error in reading the file "+OpenName+"\n")
errorDialog(u"Error in reading the file "+OpenName)
self.PBA_progressBar.setValue(0)
#read parameter
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).SetString("Version",__version__ + " (" + __date__ + ")")#
pathFile = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/FCTexture").GetString("Path")
if pathFile == "":
pathFile = path
#write parameter
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros" + __title__).SetString("Path",pathFile)
####
SingleStepC = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).GetFloat("SingleStep")
if SingleStepC == 0:
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macros/FCMmacros/" + __title__).SetFloat("SingleStep",SingleStep)
else:
SingleStep = SingleStepC
##################################################################################################
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow(MainWindow)
MainWindow.show()
@aktienmakler
Copy link

The module didn't work with Linux and Python3.
Perhaps due to my missing knowledge in submitting a proper pull request, I forked and changed your code.
#https://gist.github.com/aktienmakler/216b056587f5fbfe7640ea7932784bd9
The changes seem to be minor, but using these your module worked for me.

Thanks

@mario52a
Copy link
Author

Hi

thanks for appreciate and use my macro

i tray your modification on Windows10 and FC

OS: Windows 10 (10.0)
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.19.23463 (Git)
Build type: Release
Branch: master
Hash: adc6db8f32c17e9f67cb82aa7962d1e42ce061c6
Python version: 3.6.8
Qt version: 5.12.1
Coin version: 4.0.0a
OCC version: 7.3.0

and your modification give one error in path file:

FCTexture_Example_8Bits.bmp
Read the file FCTexture_Example_8Bits.bmp
Traceback (most recent call last):
  File "C:/Users/xxxx/AppData/Roaming/FreeCAD/Macro/FCTexturex.FCMacro", line 904, in on_PB_01_File_Launch_clicked
    f = io.open(OpenName, "rb")
FileNotFoundError: [Errno 2] No such file or directory: 'FCTexture_Example_8Bits.bmp'
End FCTexture

the cause : the variable OpenName = SaveNameformatFichier must be (complete path)
C:/Tmp/FCTexture_Example_8Bits.bmp

as my comment

                ####new
                pathFile      = SaveName[:SaveName.rfind("/") + 1] #= C:/Provisoire400/
                dummy         = SaveName.split('.')                #= ['C:/Provisoire400/image3D', 'png']
                formatFichier = "." + dummy[1]                     #= .png
                SaveName      = dummy[0]                           #= C:/Provisoire400/image3D
                SaveNameformatFichier = SaveName + formatFichier   #= C:/Provisoire400/image3D.png
                ####new

instead you modification
FCTexture_Example_8Bits.bmp

have you test the modification with different files on different path ?

for the time ok already said, i prefer delete it and wait the 0.19 official version

mario

@aktienmakler
Copy link

Hi.
I tested it with (some) different files, but maybe they were in the same directory, so it wasn't a full test...
IMHO it is a problem with the slashes and "." in the file path.
Using (my) Linux the macros are located in [user]/.FreeCAD/Macro/ and some of the pictures were there too.
The leading "." might be a problem while splitting the path in "dummy".

@mario52a
Copy link
Author

mario52a commented Jan 3, 2021

hi

happy New Year

[user]/.FreeCAD/Macro/

ok i tray with USB key and AppImage i report later

for the time i add the 2 mode:

                try:
                    arrivee = time.clock()
                    FreeCAD.Console.PrintMessage("Time : "+str("%.2f" % ((arrivee - depart)/60))+" min"+"\n")
                except Exception:
                    try:
                        arrivee = time.process_time()
                        FreeCAD.Console.PrintMessage("Time : "+str("%.2f" % ((arrivee - depart)/60))+" min"+"\n")
                    except Exception: None

mario

@mario52a
Copy link
Author

mario52a commented Jan 6, 2021

hi

i uprgade the macro version = "0.14"

i change my procedure for accept the "." point "/home/kubuntu/.FreeCAD/Macro/Texture_007_H" with more conventional command and compatible with my old procedure:

                ####new2
                pathFile      = os.path.dirname(SaveName) + "/"  #= C:/Provisoire400/
                formatFichier = os.path.splitext(SaveName)[1]    #= .png
                SaveName      = os.path.splitext(SaveName)[0]    #= /home/kubuntu/.FreeCAD/Macro/Texture_007_H #= C:/Provisoire400/image3D
                SaveNameformatFichier = SaveName + formatFichier #= C:/Provisoire400/image3D.png
                ####new2


and tested with :

#OS: Windows 10 (10.0)                          #OS: Ubuntu 20.10 (KDE/plasma) 
#Word size of OS: 64-bit                        #Word size of OS: 64-bit 
#Word size of FreeCAD: 64-bit                   #Word size of FreeCAD: 64-bit 
#Version: 0.19.23546 (Git)                      #Version: 0.19.23578 (Git) 
#Build type: Release                            #AppImage Build type: Release 
#Branch: master                                 #Branch: master 
#Hash: 6b017f9a16b15b0e628c8d874c4058442dee5548 #Hash: 50c3cbf00579dc4941ca743c25720d016b0453ce 
#Python version: 3.6.8                          #Python version: 3.8.6 
#Qt version: 5.12.1                             #Qt version: 5.12.5 
#Coin version: 4.0.0a                           #Coin version: 4.0.0 OCC 
#OCC version: 7.3.0                             #version: 7.4.0
#Locale: French/Mars (fr_MA)                    #Locale: French/Mars (fr_MA)

i adding also parameter for test if you must upgrade the macro (see User parameter:BaseApp/Preferences/Macros/FCMmacros/FCTexture

tell my if all is well ...

mario

@7profy
Copy link

7profy commented Nov 19, 2023

Hi!
Grayscale 8-bit bitmaps saved by Photoshop have no palette, so couleurs = 0 (BITMAPINFOHEADER.biClrUsed = 0).

To solve this, add after line #1001
if couleurs == 0: couleurs = 1 << bits_pixel

@mario52a
Copy link
Author

Hi

thanks for report this error,

can you share please a small image Grayscale 8-bit bitmaps saved by Photoshop ex: 200 x 200 (+/-)

thanks

mario

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment