diff --git a/src/Mod/AddonManager/AddonManager.py b/src/Mod/AddonManager/AddonManager.py
index a70bb57f29..1d8517992c 100644
--- a/src/Mod/AddonManager/AddonManager.py
+++ b/src/Mod/AddonManager/AddonManager.py
@@ -258,10 +258,16 @@ class CommandAddonManager:
from PySide import QtGui
self.repos.append(addon_repo)
- if addon_repo[2] == 1 :
- self.dialog.listWorkbenches.addItem(QtGui.QListWidgetItem(QtGui.QIcon(":/icons/button_valid.svg"),str(addon_repo[0]) + str(" ("+translate("AddonsInstaller","Installed")+")")))
+ import AddonManager_rc
+ addonicon = QtGui.QIcon(":/icons/" + addon_repo[0] + "_workbench_icon.svg")
+ if addonicon.isNull():
+ addonicon = QtGui.QIcon(":/icons/Group.svg")
+ if addon_repo[2] == 1:
+ item = QtGui.QListWidgetItem(addonicon,str(addon_repo[0]) + str(" ("+translate("AddonsInstaller","Installed")+")"))
+ item.setBackground(QtGui.QBrush(QtGui.QColor(0,182,41)))
+ self.dialog.listWorkbenches.addItem(item)
else:
- self.dialog.listWorkbenches.addItem(QtGui.QListWidgetItem(QtGui.QIcon(":/icons/Group.svg"),str(addon_repo[0])))
+ self.dialog.listWorkbenches.addItem(QtGui.QListWidgetItem(addonicon,str(addon_repo[0])))
def show_information(self, label):
@@ -358,7 +364,9 @@ class CommandAddonManager:
from PySide import QtGui
self.macros.append(macro)
if macro.is_installed():
- self.dialog.listMacros.addItem(QtGui.QListWidgetItem(QtGui.QIcon(":/icons/button_valid.svg"), macro.name + str(' (Installed)')))
+ item = QtGui.QListWidgetItem(QtGui.QIcon(":/icons/applications-python.svg"), macro.name + str(' (Installed)'))
+ item.setBackground(QtGui.QBrush(QtGui.QColor(0,182,41)))
+ self.dialog.listMacros.addItem(item)
else:
self.dialog.listMacros.addItem(QtGui.QListWidgetItem(QtGui.QIcon(":/icons/applications-python.svg"),macro.name))
@@ -400,15 +408,13 @@ class CommandAddonManager:
"shows or hides the progress bar"
if state == True:
- self.dialog.listWorkbenches.setEnabled(False)
- self.dialog.listMacros.setEnabled(False)
+ self.dialog.tabWidget.setEnabled(False)
self.dialog.buttonInstall.setEnabled(False)
self.dialog.buttonUninstall.setEnabled(False)
self.dialog.progressBar.show()
else:
self.dialog.progressBar.hide()
- self.dialog.listWorkbenches.setEnabled(True)
- self.dialog.listMacros.setEnabled(True)
+ self.dialog.tabWidget.setEnabled(True)
if not (self.firsttime and self.firstmacro):
self.dialog.buttonInstall.setEnabled(True)
self.dialog.buttonUninstall.setEnabled(True)
@@ -535,7 +541,7 @@ class CommandAddonManager:
wb[2] = 0
for macro in self.macros:
if macro.is_installed():
- self.dialog.listMacros.addItem(QtGui.QListWidgetItem(QtGui.QIcon(":/icons/button_valid.svg"), macro.name + " ("+translate("AddonsInstaller","Installed")+")"))
+ self.dialog.listMacros.addItem(item)
else:
self.dialog.listMacros.addItem(QtGui.QListWidgetItem(QtGui.QIcon(":/icons/applications-python.svg"),+macro.name))
@@ -548,7 +554,7 @@ class CommandAddonManager:
w = self.dialog.listWorkbenches.item(i)
if w.text().startswith(str(repo)):
w.setText(str(repo) + str(" ("+translate("AddonsInstaller","Update available")+")"))
- w.setIcon(QtGui.QIcon(":/icons/debug-marker.svg"))
+ w.setBackground(QtGui.QBrush(QtGui.QColor(182,90,0)))
if not repo in self.doUpdate:
self.doUpdate.append(repo)
diff --git a/src/Mod/AddonManager/CMakeLists.txt b/src/Mod/AddonManager/CMakeLists.txt
index b155ae4087..23549f18c6 100644
--- a/src/Mod/AddonManager/CMakeLists.txt
+++ b/src/Mod/AddonManager/CMakeLists.txt
@@ -1,3 +1,7 @@
+IF (BUILD_GUI)
+ PYSIDE_WRAP_RC(AddonManager_QRC_SRCS Resources/AddonManager.qrc)
+ENDIF (BUILD_GUI)
+
SET(AddonManager_SRCS
Init.py
InitGui.py
@@ -12,14 +16,24 @@ SET(AddonManager_SRCS
SOURCE_GROUP("" FILES ${AddonManager_SRCS})
ADD_CUSTOM_TARGET(AddonManager ALL
- SOURCES ${AddonManager_SRCS}
+ SOURCES ${AddonManager_SRCS} ${AddonManager_QRC_SRCS}
)
fc_copy_sources(AddonManager "${CMAKE_BINARY_DIR}/Mod/AddonManager" ${AddonManager_SRCS})
+IF (BUILD_GUI)
+ fc_target_copy_resource(AddonManager
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/Mod/AddonManager
+ AddonManager_rc.py)
+ENDIF (BUILD_GUI)
+
INSTALL(
FILES
${AddonManager_SRCS}
+ ${AddonManager_QRC_SRCS}
DESTINATION
Mod/AddonManager
)
+
+
diff --git a/src/Mod/AddonManager/Resources/AddonManager.qrc b/src/Mod/AddonManager/Resources/AddonManager.qrc
new file mode 100644
index 0000000000..d8f0fde874
--- /dev/null
+++ b/src/Mod/AddonManager/Resources/AddonManager.qrc
@@ -0,0 +1,31 @@
+
+
+ icons/A2plus_workbench-icon.svg
+ icons/Airplane_workbench-icon.svg
+ icons/Arch_Textures_workbench_icon.svg
+ icons/BIM_workbench_icon.svg
+ icons/BOLTS_workbench_icon.svg
+ icons/cfd_workbench_icon.svg
+ icons/Curves_workbench_icon.svg
+ icons/Defeaturing_workbench_icon.svg
+ icons/Dodo_workbench_icon.svg
+ icons/EM_workbench_icon.svg
+ icons/ExplodedAssembly_workbench_icon.svg
+ icons/Fasteners_workbench_icon.svg
+ icons/Flamingo_workbench_icon.svg
+ icons/GDT_workbench_icon.svg
+ icons/Gears_workbench_icon.svg
+ icons/Glider_workbench_icon.svg
+ icons/Kicad-StepUp-tools-workbench_icon.svg
+ icons/Lattice2_workbench_icon.svg
+ icons/Lithophane_workbench_icon.svg
+ icons/Manipulator_workbench_icon.svg
+ icons/PartOMagic_workbench_icon.svg
+ icons/Plot_workbench_icon.svg
+ icons/Pyrate_workbench_icon.svg
+ icons/Reporting_workbench_icon.svg
+ icons/SheetMetal_workbench_icon.svg
+ icons/Ship_workbench_icon.svg
+ icons/Timber_workbench_icon.svg
+
+
diff --git a/src/Mod/AddonManager/addonmanager_utilities.py b/src/Mod/AddonManager/addonmanager_utilities.py
index b382697672..df9913a130 100644
--- a/src/Mod/AddonManager/addonmanager_utilities.py
+++ b/src/Mod/AddonManager/addonmanager_utilities.py
@@ -97,6 +97,17 @@ def urlopen(url):
return u
+def getserver(url):
+
+ """returns the server part of an url"""
+
+ if sys.version_info.major < 3:
+ from urlparse import urlparse
+ else:
+ from urllib.parse import urlparse
+ return '{uri.scheme}://{uri.netloc}/'.format(uri=urlparse(url))
+
+
def update_macro_details(old_macro, new_macro):
"""Update a macro with information from another one
diff --git a/src/Mod/AddonManager/addonmanager_workers.py b/src/Mod/AddonManager/addonmanager_workers.py
index 9ab6673ad3..c5d99fc732 100644
--- a/src/Mod/AddonManager/addonmanager_workers.py
+++ b/src/Mod/AddonManager/addonmanager_workers.py
@@ -35,6 +35,7 @@ from addonmanager_macro import Macro
from addonmanager_utilities import urlopen
from addonmanager_utilities import translate
from addonmanager_utilities import symlink
+from addonmanager_utilities import getserver
MACROS_BLACKLIST = ["BOLTS","WorkFeatures","how to install","PartsLibrary","FCGear"]
OBSOLETE = ["assembly2","drawing_dimensioning","cura_engine"] # These addons will print an additional message informing the user
@@ -382,12 +383,12 @@ class ShowWorker(QtCore.QThread):
self.info_label.emit( message )
self.progressbar_show.emit(False)
- l = self.loadImages( message )
+ l = self.loadImages( message, url )
if l:
self.info_label.emit( l )
self.stop = True
- def loadImages(self,message):
+ def loadImages(self,message,url):
"checks if the given page contains images and downloads them"
@@ -402,6 +403,11 @@ class ShowWorker(QtCore.QThread):
if not os.path.exists(store):
os.makedirs(store)
for path in imagepaths:
+ if "?" in path:
+ # remove everything after the ?
+ path = path.split("?")[0]
+ if not path.startswith("http"):
+ path = getserver(url) + path
name = path.split("/")[-1]
if name and path.startswith("http"):
storename = os.path.join(store,name)
@@ -426,7 +432,7 @@ class ShowWorker(QtCore.QThread):
pix = pix.fromImage(img.scaled(300,300,QtCore.Qt.KeepAspectRatio,QtCore.Qt.FastTransformation))
pix.save(storename, "jpeg",100)
- message = message.replace(path,"file://"+storename.replace("\\","/"))
+ message = message.replace(path,"file:///"+storename.replace("\\","/"))
return message
return None
@@ -547,7 +553,7 @@ class InstallWorker(QtCore.QThread):
try:
answer = repo.pull()
except:
- print("Error updating module",repos[idx][1]," - Please fix manually")
+ print("Error updating module",self.repos[idx][1]," - Please fix manually")
answer = repo.status()
print(answer)
else:
diff --git a/src/Mod/Arch/ArchFence.py b/src/Mod/Arch/ArchFence.py
index 023bb3f741..94d70cb96e 100644
--- a/src/Mod/Arch/ArchFence.py
+++ b/src/Mod/Arch/ArchFence.py
@@ -58,6 +58,15 @@ class _Fence(ArchComponent.Component):
self.Type = "Fence"
+ def __getstate__(self):
+ return (self.sectionFaceNumbers)
+
+ def __setstate__(self, state):
+ if state is not None and isinstance(state, tuple):
+ self.sectionFaceNumbers = state[0]
+
+ return None
+
def execute(self, obj):
import Part
@@ -97,7 +106,7 @@ class _Fence(ArchComponent.Component):
obj, pathwire, downRotation)
postShapes = self.calculatePosts(obj, postPlacements)
- sectionShapes = self.calculateSections(
+ sectionShapes, sectionFaceNumbers = self.calculateSections(
obj, postPlacements, postLength, sectionLength)
allShapes = []
@@ -106,6 +115,8 @@ class _Fence(ArchComponent.Component):
compound = Part.makeCompound(allShapes)
+ self.sectionFaceNumbers = sectionFaceNumbers
+
self.applyShape(obj, compound, obj.Placement,
allowinvalid=True, allownosolid=True)
@@ -146,6 +157,11 @@ class _Fence(ArchComponent.Component):
shapes = []
+ # For the colorization algorithm we have to store the number of faces for each section
+ # It is possible that a section is clipped. Then the number of faces is not equals to the
+ # number of faces in the original section
+ faceNumbers = []
+
for i in range(obj.NumberOfSections):
startPlacement = postPlacements[i]
endPlacement = postPlacements[i + 1]
@@ -175,8 +191,9 @@ class _Fence(ArchComponent.Component):
sectionCopy.Placement = placement
shapes.append(sectionCopy)
+ faceNumbers.append(len(sectionCopy.Faces))
- return shapes
+ return (shapes, faceNumbers)
def clipSection(self, shape, length, clipLength):
import Part
@@ -189,14 +206,12 @@ class _Fence(ArchComponent.Component):
FreeCAD.Vector(boundBox.XMin, boundBox.YMin, boundBox.ZMin))
rightBox = Part.makeBox(halfLengthToCut, boundBox.YMax + 1, boundBox.ZMax + 1,
FreeCAD.Vector(boundBox.XMin + halfLengthToCut + clipLength, boundBox.YMin, boundBox.ZMin))
-
+
newShape = shape.cut([leftBox, rightBox])
newBoundBox = newShape.BoundBox
newShape.translate(FreeCAD.Vector(-newBoundBox.XMin, 0, 0))
- print(newShape.BoundBox)
-
return newShape.removeSplitter()
def calculatePathWire(self, obj):
@@ -214,6 +229,17 @@ class _ViewProviderFence(ArchComponent.ViewProviderComponent):
def __init__(self, vobj):
ArchComponent.ViewProviderComponent.__init__(self, vobj)
+ self.setProperties(vobj)
+
+ def setProperties(self, vobj):
+ pl = vobj.PropertiesList
+
+ if not "UseOriginalColors" in pl:
+ vobj.addProperty("App::PropertyBool", "UseOriginalColors", "Fence", QT_TRANSLATE_NOOP(
+ "App::Property", "When true, the fence will be colored like the original post and section."))
+
+ def onDocumentRestored(self, vobj):
+ self.setProperties(vobj)
def getIcon(self):
import Arch_rc
@@ -234,6 +260,93 @@ class _ViewProviderFence(ArchComponent.ViewProviderComponent):
return children
+ def updateData(self, obj, prop):
+ colorProps = ["Shape", "Section", "Post", "Path"]
+
+ if prop in colorProps:
+ self.applyColors(obj)
+ else:
+ super().updateData(obj, prop)
+
+ def onChanged(self, vobj, prop):
+ if prop == "UseOriginalColors":
+ self.applyColors(vobj.Object)
+ else:
+ super().onChanged(vobj, prop)
+
+ def applyColors(self, obj):
+ if not hasattr(obj.ViewObject, "UseOriginalColors") or not obj.ViewObject.UseOriginalColors:
+ obj.ViewObject.DiffuseColor = [obj.ViewObject.ShapeColor]
+ else:
+ post = obj.Post
+ section = obj.Section
+
+ numberOfPostFaces = len(post.Shape.Faces)
+ numberOfSectionFaces = len(section.Shape.Faces)
+
+ if hasattr(obj.Proxy, 'sectionFaceNumbers'):
+ sectionFaceNumbers = obj.Proxy.sectionFaceNumbers
+ else:
+ sectionFaceNumbers = [0]
+
+ if numberOfPostFaces == 0 or sum(sectionFaceNumbers) == 0:
+ return
+
+ postColors = self.normalizeColors(post, numberOfPostFaces)
+ defaultSectionColors = self.normalizeColors(
+ section, numberOfSectionFaces)
+
+ ownColors = []
+
+ # At first all posts are added to the shape
+ for i in range(obj.NumberOfPosts):
+ ownColors.extend(postColors)
+
+ # Next all sections are added
+ for i in range(obj.NumberOfSections):
+ actualSectionFaceCount = sectionFaceNumbers[i]
+
+ if actualSectionFaceCount == numberOfSectionFaces:
+ ownColors.extend(defaultSectionColors)
+ else:
+ ownColors.extend(self.normalizeColors(
+ section, actualSectionFaceCount))
+
+ viewObject = obj.ViewObject
+ viewObject.DiffuseColor = ownColors
+
+ def normalizeColors(self, obj, numberOfFaces):
+ colors = obj.ViewObject.DiffuseColor
+
+ if obj.TypeId == 'PartDesign::Body':
+ # When colorizing a PartDesign Body we have two options
+ # 1. The whole body got a shape color, that means the tip has only a single diffuse color set
+ # so we use the shape color of the body
+ # 2. "Set colors" was called on the tip and the individual faces where colorized.
+ # We use the diffuseColors of the tip in that case
+ tipColors = obj.Tip.ViewObject.DiffuseColor
+
+ if len(tipColors) > 1:
+ colors = tipColors
+
+ numberOfColors = len(colors)
+
+ if numberOfColors == 1:
+ return colors * numberOfFaces
+
+ colorsToUse = colors.copy()
+
+ if numberOfColors == numberOfFaces:
+ return colorsToUse
+ else:
+ # It is possible, that we have less faces than colors when something got clipped.
+ # Remove the unneeded colors at the beginning and end
+ halfNumberOfFacesToRemove = (numberOfColors - numberOfFaces) / 2
+ start = int(math.ceil(halfNumberOfFacesToRemove))
+ end = start + numberOfFaces
+
+ return colorsToUse[start:end]
+
class _CommandFence:
"the Arch Fence command definition"
@@ -330,12 +443,30 @@ if __name__ == '__main__':
def buildPost():
post = Part.makeBox(100, 100, 1000, FreeCAD.Vector(0, 0, 0))
- Part.show(post, "Post")
+ Part.show(post, 'Post')
return FreeCAD.ActiveDocument.getObject('Post')
+ def colorizeFaces(o, color=(0.6, 0.0, 0.0, 0.0), faceIndizes=[2]):
+ numberOfFaces = len(o.Shape.Faces)
+ vo = o.ViewObject
+
+ originalColors = vo.DiffuseColor
+
+ if len(originalColors) == 1:
+ newColors = originalColors * numberOfFaces
+ else:
+ newColors = originalColors.copy()
+
+ for i in faceIndizes:
+ newColors[i] = color
+
+ vo.DiffuseColor = newColors
+
section = buildSection()
path = buildPath()
post = buildPost()
+ colorizeFaces(post)
+
print(makeFence(section, post, path))
diff --git a/src/Mod/Arch/ArchIFC.py b/src/Mod/Arch/ArchIFC.py
index a64a4f65d2..45baa0728c 100644
--- a/src/Mod/Arch/ArchIFC.py
+++ b/src/Mod/Arch/ArchIFC.py
@@ -45,6 +45,7 @@ def getIfcProduct(IfcType):
name = "IfcBuildingElementProxy"
if name in ArchIFCSchema.IfcProducts:
return ArchIFCSchema.IfcProducts[name]
+ return None
def getIfcProductAttribute(ifcProduct, name):
@@ -81,6 +82,8 @@ def addIfcProductAttribute(obj, attribute):
"Adds a given attribute property"
+ if not hasattr(obj,"IfcData"):
+ return
IfcData = obj.IfcData
if "attributes" not in IfcData:
IfcData["attributes"] = "{}"
diff --git a/src/Mod/Arch/importDAE.py b/src/Mod/Arch/importDAE.py
index 3574c08696..b5082cce5e 100644
--- a/src/Mod/Arch/importDAE.py
+++ b/src/Mod/Arch/importDAE.py
@@ -189,7 +189,10 @@ def read(filename):
def export(exportList,filename,tessellation=1,colors=None):
- "called when freecad exports a file"
+ """export(exportList,filename,tessellation=1,colors=None) -- exports FreeCAD contents to a DAE file.
+ colors is an optional dictionary of objName:shapeColorTuple or objName:diffuseColorList elements
+ to be used in non-GUI mode if you want to be able to export colors. Tessellation is used when breaking
+ curved surfaces into triangles."""
if not checkCollada(): return
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py
index 8017494b31..1d85dd052f 100644
--- a/src/Mod/Arch/importIFC.py
+++ b/src/Mod/Arch/importIFC.py
@@ -1466,7 +1466,9 @@ class recycler:
def export(exportList,filename,colors=None):
- "exports FreeCAD contents to an IFC file"
+ """export(exportList,filename,colors=None) -- exports FreeCAD contents to an IFC file.
+ colors is an optional dictionary of objName:shapeColorTuple or objName:diffuseColorList elements
+ to be used in non-GUI mode if you want to be able to export colors."""
getPreferences()
diff --git a/src/Mod/Arch/importOBJ.py b/src/Mod/Arch/importOBJ.py
index 5aaef03621..dde94cc9f6 100644
--- a/src/Mod/Arch/importOBJ.py
+++ b/src/Mod/Arch/importOBJ.py
@@ -220,7 +220,7 @@ def export(exportList,filename,colors=None):
outfile = pythonopen(filenamemtl,"w")
outfile.write("# FreeCAD v" + ver[0] + "." + ver[1] + " build" + ver[2] + " Arch module\n")
outfile.write("# http://www.freecadweb.org\n")
- kinds = {"AmbientColor":"Ka ","DiffuseColor":"Kd ","SpecularColor":"Ks ","EmissiveColor":"Ke ","Transparency":"d "}
+ kinds = {"AmbientColor":"Ka ","DiffuseColor":"Kd ","SpecularColor":"Ks ","EmissiveColor":"Ke ","Transparency":"Tr "}
done = [] # store names to avoid duplicates
for mat in materials:
if isinstance(mat,tuple):
diff --git a/src/Mod/PartDesign/App/FeaturePad.cpp b/src/Mod/PartDesign/App/FeaturePad.cpp
index b26599cd25..32fcea5291 100644
--- a/src/Mod/PartDesign/App/FeaturePad.cpp
+++ b/src/Mod/PartDesign/App/FeaturePad.cpp
@@ -218,6 +218,8 @@ App::DocumentObjectExecReturn *Pad::execute(void)
TopExp_Explorer Ex(supportface,TopAbs_WIRE);
if (!Ex.More())
supportface = TopoDS_Face();
+
+#if 0
BRepFeat_MakePrism PrismMaker;
PrismMaker.Init(base, sketchshape, supportface, dir, 2, 1);
PrismMaker.Perform(upToFace);
@@ -225,6 +227,9 @@ App::DocumentObjectExecReturn *Pad::execute(void)
if (!PrismMaker.IsDone())
return new App::DocumentObjectExecReturn("Pad: Up to face: Could not extrude the sketch!");
prism = PrismMaker.Shape();
+#else
+ generatePrism(prism, method, base, sketchshape, supportface, upToFace, dir, 2, 1);
+#endif
base.Nullify();
} else {
// A support object is always required and we need to use BRepFeat_MakePrism
@@ -239,6 +244,7 @@ App::DocumentObjectExecReturn *Pad::execute(void)
TopExp_Explorer Ex(supportface,TopAbs_WIRE);
if (!Ex.More())
supportface = TopoDS_Face();
+#if 0
BRepFeat_MakePrism PrismMaker;
PrismMaker.Init(base, sketchshape, supportface, dir, 2, 1);
PrismMaker.Perform(upToFace);
@@ -246,6 +252,9 @@ App::DocumentObjectExecReturn *Pad::execute(void)
if (!PrismMaker.IsDone())
return new App::DocumentObjectExecReturn("Pad: Up to face: Could not extrude the sketch!");
prism = PrismMaker.Shape();
+#else
+ generatePrism(prism, method, base, sketchshape, supportface, upToFace, dir, 2, 1);
+#endif
}
} else {
generatePrism(prism, sketchshape, method, dir, L, L2,
diff --git a/src/Mod/PartDesign/App/FeaturePocket.cpp b/src/Mod/PartDesign/App/FeaturePocket.cpp
index 0124db278f..57933f63a1 100644
--- a/src/Mod/PartDesign/App/FeaturePocket.cpp
+++ b/src/Mod/PartDesign/App/FeaturePocket.cpp
@@ -174,6 +174,7 @@ App::DocumentObjectExecReturn *Pocket::execute(void)
TopExp_Explorer Ex(supportface,TopAbs_WIRE);
if (!Ex.More())
supportface = TopoDS_Face();
+#if 0
BRepFeat_MakePrism PrismMaker;
PrismMaker.Init(base, profileshape, supportface, dir, 0, 1);
PrismMaker.Perform(upToFace);
@@ -181,6 +182,10 @@ App::DocumentObjectExecReturn *Pocket::execute(void)
if (!PrismMaker.IsDone())
return new App::DocumentObjectExecReturn("Pocket: Up to face: Could not extrude the sketch!");
TopoDS_Shape prism = PrismMaker.Shape();
+#else
+ TopoDS_Shape prism;
+ generatePrism(prism, method, base, profileshape, supportface, upToFace, dir, 0, 1);
+#endif
// And the really expensive way to get the SubShape...
BRepAlgoAPI_Cut mkCut(base, prism);
diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.cpp b/src/Mod/PartDesign/App/FeatureSketchBased.cpp
index baaa7363af..5b7900e085 100644
--- a/src/Mod/PartDesign/App/FeatureSketchBased.cpp
+++ b/src/Mod/PartDesign/App/FeatureSketchBased.cpp
@@ -34,6 +34,7 @@
# include
# include
# include
+# include
# include
# include
# include
@@ -544,6 +545,35 @@ void ProfileBased::generatePrism(TopoDS_Shape& prism,
}
+void ProfileBased::generatePrism(TopoDS_Shape& prism,
+ const std::string& method,
+ const TopoDS_Shape& baseshape,
+ const TopoDS_Shape& profileshape,
+ const TopoDS_Face& sketchface,
+ const TopoDS_Face& uptoface,
+ const gp_Dir& direction,
+ Standard_Integer Mode,
+ Standard_Boolean Modify)
+{
+ if (method == "UpToFirst" || method == "UpToFace") {
+ BRepFeat_MakePrism PrismMaker;
+ TopoDS_Shape base = baseshape;
+ TopoDS_Face supportface = sketchface;
+ for (TopExp_Explorer xp(profileshape, TopAbs_FACE); xp.More(); xp.Next()) {
+ PrismMaker.Init(base, xp.Current(), supportface, direction, Mode, Modify);
+ PrismMaker.Perform(uptoface);
+ if (!PrismMaker.IsDone())
+ throw Base::RuntimeError("ProfileBased: Up to face: Could not extrude the sketch!");
+
+ base = PrismMaker.Shape();
+ if (Mode == 2)
+ Mode = 1;
+ }
+
+ prism = base;
+ }
+}
+
bool ProfileBased::checkWireInsideFace(const TopoDS_Wire& wire, const TopoDS_Face& face,
const gp_Dir& dir) {
// Project wire onto the face (face, not surface! So limits of face apply)
diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.h b/src/Mod/PartDesign/App/FeatureSketchBased.h
index 6309df0976..f5c13789aa 100644
--- a/src/Mod/PartDesign/App/FeatureSketchBased.h
+++ b/src/Mod/PartDesign/App/FeatureSketchBased.h
@@ -134,6 +134,19 @@ protected:
const double L2,
const bool midplane,
const bool reversed);
+ /**
+ * Generate a linear prism
+ * It will be a stand-alone solid created with BRepFeat_MakePrism
+ */
+ static void generatePrism(TopoDS_Shape& prism,
+ const std::string& method,
+ const TopoDS_Shape& baseshape,
+ const TopoDS_Shape& profileshape,
+ const TopoDS_Face& sketchface,
+ const TopoDS_Face& uptoface,
+ const gp_Dir& direction,
+ Standard_Integer Mode,
+ Standard_Boolean Modify);
/// Check whether the wire after projection on the face is inside the face
static bool checkWireInsideFace(const TopoDS_Wire& wire,