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,