diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py
index dad02306d3..8e163e6670 100644
--- a/src/Mod/Arch/ArchSectionPlane.py
+++ b/src/Mod/Arch/ArchSectionPlane.py
@@ -95,7 +95,37 @@ def makeSectionView(section,name="View"):
view.Label = translate("Arch","View of")+" "+section.Name
return view
+def getSectionData(source):
+
+ """Returns some common data from section planes and building parts"""
+
+ if hasattr(source,"Objects"):
+ objs = source.Objects
+ cutplane = source.Shape
+ elif hasattr(source,"Group"):
+ import Part
+ objs = source.Group
+ cutplane = Part.makePlane(1000,1000,FreeCAD.Vector(-500,-500,0))
+ m = 1
+ if source.ViewObject and hasattr(source.ViewObject,"CutMargin"):
+ m = source.ViewObject.CutMargin.Value
+ cutplane.translate(FreeCAD.Vector(0,0,m))
+ cutplane.Placement = cutplane.Placement.multiply(source.Placement)
+ onlySolids = True
+ if hasattr(source,"OnlySolids"):
+ onlySolids = source.OnlySolids
+ clip = False
+ if hasattr(source,"Clip"):
+ clip = source.Clip
+ p = FreeCAD.Placement(source.Placement)
+ direction = p.Rotation.multVec(FreeCAD.Vector(0,0,1))
+ if objs:
+ objs = Draft.getGroupContents(objs,walls=True,addgroups=True)
+ return objs,cutplane,onlySolids,clip,direction
+
+
def looksLikeDraft(o):
+
# If there is no shape at all ignore it
if not hasattr(o, 'Shape') or o.Shape.isNull():
return False
@@ -106,7 +136,7 @@ def looksLikeDraft(o):
# If we have a shape, but no volume, it looks like a flat 2D object
return o.Shape.Volume < 0.0000001 # add a little tolerance...
-def getCutShapes(objs,section,showHidden,groupSshapesByObject=False):
+def getCutShapes(objs,cutplane,onlySolids,clip,joinArch,showHidden,groupSshapesByObject=False):
import Part,DraftGeomUtils
shapes = []
@@ -114,28 +144,53 @@ def getCutShapes(objs,section,showHidden,groupSshapesByObject=False):
sshapes = []
objectShapes = []
objectSshapes = []
- for o in objs:
- if o.isDerivedFrom("Part::Feature"):
- if o.Shape.isNull():
- pass
- elif section.OnlySolids:
- if o.Shape.isValid():
- solids = []
- solids.extend(o.Shape.Solids)
- shapes.extend(solids)
-
- objectShapes.append((o, solids))
+ if joinArch:
+ shtypes = {}
+ for o in objs:
+ if Draft.getType(o) in ["Wall","Structure"]:
+ if o.Shape.isNull():
+ pass
+ elif onlySolids:
+ shtypes.setdefault(o.Material.Name if (hasattr(o,"Material") and o.Material) else "None",[]).extend(o.Shape.Solids)
else:
- print(section.Label,": Skipping invalid object:",o.Label)
+ shtypes.setdefault(o.Material.Name if (hasattr(o,"Material") and o.Material) else "None",[]).append(o.Shape.copy())
+ elif o.isDerivedFrom("Part::Feature"):
+ if o.Shape.isNull():
+ pass
+ elif onlySolids:
+ shapes.extend(o.Shape.Solids)
+ objectShapes.append((o, o.Shape.Solids))
+ else:
+ shapes.append(o.Shape.copy())
+ objectShapes.append((o,[o.Shape.copy()]))
+ for k,v in shtypes.items():
+ v1 = v.pop()
+ if v:
+ v1 = v1.multiFuse(v)
+ v1 = v1.removeSplitter()
+ if v1.Solids:
+ shapes.extend(v1.Solids)
+ objectShapes.append((k,v1.Solids))
else:
- shapes.append(o.Shape)
- objectShapes.append((o, [o.Shape]))
- clip = False
- if hasattr(section, "Clip"):
- clip = section.Clip
- cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(section.Shape.copy(),shapes,clip)
- shapes =[]
+ print("ArchSectionPlane: Fusing Arch objects produced non-solid results")
+ shapes.append(v1)
+ objectShapes.append((k,[v1]))
+ else:
+ for o in objs:
+ if o.isDerivedFrom("Part::Feature"):
+ if o.Shape.isNull():
+ pass
+ elif onlySolids:
+ if o.Shape.isValid():
+ shapes.extend(o.Shape.Solids)
+ objectShapes.append((o,o.Shape.Solids))
+ else:
+ shapes.append(o.Shape)
+ objectShapes.append((o,[o.Shape]))
+
+ cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(cutplane,shapes,clip)
+ shapes = []
if cutvolume:
for o, shapeList in objectShapes:
tmpSshapes = []
@@ -172,22 +227,37 @@ def getCutShapes(objs,section,showHidden,groupSshapesByObject=False):
else:
return shapes,hshapes,sshapes,cutface,cutvolume,invcutvolume
-def getFillForObject(o, defaultFill, section):
- if hasattr(section, 'UseMaterialColorForFill') and section.UseMaterialColorForFill:
+def getFillForObject(o, defaultFill, source):
+
+ if hasattr(source, 'UseMaterialColorForFill') and source.UseMaterialColorForFill:
+ material = None
if hasattr(o, 'Material') and o.Material:
material = o.Material
-
+ elif isinstance(o,str):
+ material = FreeCAD.ActiveDocument.getObject(o)
+ if material:
if hasattr(material, 'Color') and material.Color:
- return o.Material.Color
-
+ return material.Color
return defaultFill
-def getSVG(section, renderMode="Wireframe", allOn=False, showHidden=False, scale=1, rotation=0, linewidth=1, lineColor=(0.0,0.0,0.0), fontsize=1, showFill=False, fillColor=(0.8,0.8,0.8), techdraw=False,fillSpaces=False):
+def getSVG(source,
+ renderMode="Wireframe",
+ allOn=False,
+ showHidden=False,
+ scale=1,
+ rotation=0,
+ linewidth=1,
+ lineColor=(0.0,0.0,0.0),
+ fontsize=1,
+ showFill=False,
+ fillColor=(0.8,0.8,0.8),
+ techdraw=False,
+ fillSpaces=False,
+ cutlinewidth=0,
+ joinArch=False):
- """getSVG(section, [renderMode, allOn, showHidden, scale, rotation,
- linewidth, lineColor, fontsize, showFill, fillColor, techdraw, fillSpaces]):
-
- returns an SVG fragment from an Arch section plane. If
+ """
+ returns an SVG fragment from an Arch SectionPlane or BuildingPart. If
allOn is True, all cut objects are shown, regardless if they are visible or not.
renderMode can be Wireframe (default) or Solid to use the Arch solid renderer. If
showHidden is True, the hidden geometry above the section plane is shown in dashed line.
@@ -198,12 +268,10 @@ def getSVG(section, renderMode="Wireframe", allOn=False, showHidden=False, scale
fillSpaces - If True, shows space objects as filled surfaces
"""
- if not section.Objects:
- return ""
import Part,DraftGeomUtils
- p = FreeCAD.Placement(section.Placement)
- direction = p.Rotation.multVec(FreeCAD.Vector(0,0,1))
- objs = Draft.getGroupContents(section.Objects,walls=True,addgroups=True)
+ objs, cutplane, onlySolids, clip, direction = getSectionData(source)
+ if not objs:
+ return ""
if not allOn:
objs = Draft.removeHidden(objs)
@@ -231,8 +299,12 @@ def getSVG(section, renderMode="Wireframe", allOn=False, showHidden=False, scale
archUserParameters = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
scaledLineWidth = linewidth/scale
svgLineWidth = str(scaledLineWidth) + 'px'
- st = archUserParameters.GetFloat("CutLineThickness",2)
- svgCutLineWidth = str(scaledLineWidth * st) + 'px'
+ if cutlinewidth:
+ scaledCutLineWidth = cutlinewidth/scale
+ svgCutLineWidth = str(scaledCutLineWidth) + 'px'
+ else:
+ st = archUserParameters.GetFloat("CutLineThickness",2)
+ svgCutLineWidth = str(scaledLineWidth * st) + 'px'
yt = archUserParameters.GetFloat("SymbolLineThickness",0.6)
svgSymbolLineWidth = str(linewidth * yt)
hiddenPattern = archUserParameters.GetString("archHiddenPattern","30,10")
@@ -243,35 +315,40 @@ def getSVG(section, renderMode="Wireframe", allOn=False, showHidden=False, scale
fillpattern += ''
svgLineColor = Draft.getrgb(lineColor)
svg = ''
-
# reading cached version
svgcache = None
- if hasattr(section.Proxy,"svgcache") and section.Proxy.svgcache:
- svgcache = section.Proxy.svgcache[0]
- if section.Proxy.svgcache[1] != renderMode:
- svgcache = None
- if section.Proxy.svgcache[2] != showHidden:
- svgcache = None
- if section.Proxy.svgcache[3] != showFill:
- svgcache = None
- if section.Proxy.svgcache[4] != fillSpaces:
- svgcache = None
+ if hasattr(source,"Proxy"):
+ if hasattr(source.Proxy,"svgcache") and source.Proxy.svgcache:
+ svgcache = source.Proxy.svgcache[0]
+ # empty caches if we want to force-recalculate for certain properties
+ if source.Proxy.svgcache[1] != renderMode:
+ svgcache = None
+ if source.Proxy.svgcache[2] != showHidden:
+ svgcache = None
+ if source.Proxy.svgcache[3] != showFill:
+ svgcache = None
+ if source.Proxy.svgcache[4] != fillSpaces:
+ svgcache = None
+ source.Proxy.shapecache = None
+ if source.Proxy.svgcache[5] != joinArch:
+ svgcache = None
+ source.Proxy.shapecache = None
- if hasattr(section.Proxy,"boolcache") and section.Proxy.boolcache:
- vshapes = section.Proxy.boolcache[0]
- hshapes = section.Proxy.boolcache[1]
- sshapes = section.Proxy.boolcache[2]
- cutface = section.Proxy.boolcache[3]
- cutvolume = section.Proxy.boolcache[4]
- invcutvolume = section.Proxy.boolcache[5]
- objectSshapes = section.Proxy.boolcache[6]
- else:
- if showFill:
- vshapes,hshapes,sshapes,cutface,cutvolume,invcutvolume,objectSshapes = getCutShapes(objs,section,showHidden, True)
+ if hasattr(source.Proxy,"shapecache") and source.Proxy.shapecache:
+ vshapes = source.Proxy.shapecache[0]
+ hshapes = source.Proxy.shapecache[1]
+ sshapes = source.Proxy.shapecache[2]
+ cutface = source.Proxy.shapecache[3]
+ cutvolume = source.Proxy.shapecache[4]
+ invcutvolume = source.Proxy.shapecache[5]
+ objectSshapes = source.Proxy.shapecache[6]
else:
- vshapes,hshapes,sshapes,cutface,cutvolume,invcutvolume = getCutShapes(objs,section,showHidden)
- objectSshapes = []
- section.Proxy.boolcache = [vshapes,hshapes,sshapes,cutface,cutvolume,invcutvolume,objectSshapes]
+ if showFill:
+ vshapes,hshapes,sshapes,cutface,cutvolume,invcutvolume,objectSshapes = getCutShapes(objs,cutplane,onlySolids,clip,joinArch,showHidden,True)
+ else:
+ vshapes,hshapes,sshapes,cutface,cutvolume,invcutvolume = getCutShapes(objs,cutplane,onlySolids,clip,joinArch,showHidden)
+ objectSshapes = []
+ source.Proxy.shapecache = [vshapes,hshapes,sshapes,cutface,cutvolume,invcutvolume,objectSshapes]
# generating SVG
if renderMode in ["Solid",1]:
@@ -280,15 +357,20 @@ def getSVG(section, renderMode="Wireframe", allOn=False, showHidden=False, scale
# render using the Arch Vector Renderer
import ArchVRM, WorkingPlane
wp = WorkingPlane.plane()
- wp.setFromPlacement(section.Placement)
+ pl = FreeCAD.Placement(source.Placement)
+ if source.ViewObject and hasattr(source.ViewObject,"CutMargin"):
+ mv = pl.multVec(FreeCAD.Vector(0,0,1))
+ mv.multiply(source.ViewObject.CutMargin)
+ pl.move(mv)
+ wp.setFromPlacement(pl)
#wp.inverse()
render = ArchVRM.Renderer()
render.setWorkingPlane(wp)
render.addObjects(objs)
if showHidden:
- render.cut(section.Shape,showHidden)
+ render.cut(cutplane,showHidden)
else:
- render.cut(section.Shape)
+ render.cut(cutplane)
svgcache += '\n'
svgcache += render.getViewSVG(linewidth="SVGLINEWIDTH")
svgcache += fillpattern
@@ -298,7 +380,8 @@ def getSVG(section, renderMode="Wireframe", allOn=False, showHidden=False, scale
svgcache += render.getHiddenSVG(linewidth="SVGLINEWIDTH")
svgcache += '\n'
# print(render.info())
- section.Proxy.svgcache = [svgcache,renderMode,showHidden,showFill,fillSpaces]
+ if hasattr(source,"Proxy"):
+ source.Proxy.svgcache = [svgcache,renderMode,showHidden,showFill,fillSpaces,joinArch]
else:
if not svgcache:
@@ -329,7 +412,7 @@ def getSVG(section, renderMode="Wireframe", allOn=False, showHidden=False, scale
for o, shapes in objectSshapes:
for s in shapes:
if s.Edges:
- objectFill = getFillForObject(o, fillColor, section)
+ objectFill = getFillForObject(o, fillColor, source)
#svg += Draft.getSVG(s,direction=direction.negative(),linewidth=0,fillstyle="sectionfill",color=(0,0,0))
# temporarily disabling fill patterns
svgcache += Draft.getSVG(s, direction=direction.negative(),
@@ -344,7 +427,8 @@ def getSVG(section, renderMode="Wireframe", allOn=False, showHidden=False, scale
sshapes, direction,
hStyle=style, h0Style=style, h1Style=style,
vStyle=style, v0Style=style, v1Style=style)
- section.Proxy.svgcache = [svgcache,renderMode,showHidden,showFill,fillSpaces]
+ if hasattr(source,"Proxy"):
+ source.Proxy.svgcache = [svgcache,renderMode,showHidden,showFill,fillSpaces,joinArch]
svgcache = svgcache.replace("SVGLINECOLOR",svgLineColor)
svgcache = svgcache.replace("SVGLINEWIDTH",svgLineWidth)
svgcache = svgcache.replace("SVGHIDDENPATTERN",svgHiddenPattern)
@@ -361,7 +445,7 @@ def getSVG(section, renderMode="Wireframe", allOn=False, showHidden=False, scale
if not techdraw:
svg += ''
- # filter out spaces not cut by the section plane
+ # filter out spaces not cut by the source plane
if cutface and spaces:
spaces = [s for s in spaces if s.Shape.BoundBox.intersect(cutface.BoundBox)]
if spaces:
@@ -426,12 +510,10 @@ def getDXF(obj):
import Drawing,Part
if not obj.Source:
return result
- section = obj.Source
- if not section.Objects:
+ source = obj.Source
+ objs,cutplane,onlySolids,clip,direction = getSectionData(source)
+ if not objs:
return result
- p = FreeCAD.Placement(section.Placement)
- direction = p.Rotation.multVec(FreeCAD.Vector(0,0,1))
- objs = Draft.getGroupContents(section.Objects,walls=True,addgroups=True)
if not allOn:
objs = Draft.removeHidden(objs)
# separate spaces and Draft objects
@@ -439,7 +521,7 @@ def getDXF(obj):
nonspaces = []
drafts = []
objs = [o for o in objs if ((not(Draft.getType(o) in ["Space","Dimension","Annotation"])) and (not (o.isDerivedFrom("Part::Part2DObject"))))]
- vshapes,hshapes,sshapes,cutface,cutvolume,invcutvolume = getCutShapes(objs,section,showHidden)
+ vshapes,hshapes,sshapes,cutface,cutvolume,invcutvolume = getCutShapes(objs,cutplane,onlySolids,clip,False,showHidden)
if vshapes:
result.append(Drawing.projectToDXF(Part.makeCompound(vshapes),direction))
if sshapes:
@@ -538,7 +620,7 @@ class _SectionPlane:
# clean svg cache if needed
if prop in ["Placement","Objects","OnlySolids","UseMaterialColorForFill","Clip"]:
self.svgcache = None
- self.boolcache = None
+ self.shapecache = None
def getNormal(self,obj):
diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py
index b91de89e2e..ff13ae8754 100644
--- a/src/Mod/Draft/Draft.py
+++ b/src/Mod/Draft/Draft.py
@@ -5503,7 +5503,7 @@ class _Shape2DView(_DraftObject):
else:
objs = obj.Base.Group
cutplane = Part.makePlane(1000,1000,FreeCAD.Vector(-500,-500,0))
- m = 1500
+ m = 1
if obj.Base.ViewObject and hasattr(obj.Base.ViewObject,"CutMargin"):
m = obj.Base.ViewObject.CutMargin.Value
cutplane.translate(FreeCAD.Vector(0,0,m))
diff --git a/src/Mod/TechDraw/App/DrawViewArch.cpp b/src/Mod/TechDraw/App/DrawViewArch.cpp
index 4dca98553a..bf138b89ac 100644
--- a/src/Mod/TechDraw/App/DrawViewArch.cpp
+++ b/src/Mod/TechDraw/App/DrawViewArch.cpp
@@ -54,7 +54,7 @@ DrawViewArch::DrawViewArch(void)
{
static const char *group = "Arch view";
- ADD_PROPERTY_TYPE(Source ,(0),group,App::Prop_None,"Section Plane object for this view");
+ ADD_PROPERTY_TYPE(Source ,(0),group,App::Prop_None,"SectionPlane or BuildingPart object for this view");
Source.setScope(App::LinkScope::Global);
ADD_PROPERTY_TYPE(AllOn ,(false),group,App::Prop_None,"If hidden objects must be shown or not");
RenderMode.setEnums(RenderModeEnums);
@@ -62,8 +62,10 @@ DrawViewArch::DrawViewArch(void)
ADD_PROPERTY_TYPE(FillSpaces ,(false),group,App::Prop_None,"If True, Arch Spaces are shown as a colored area");
ADD_PROPERTY_TYPE(ShowHidden ,(false),group,App::Prop_None,"If the hidden geometry behind the section plane is shown or not");
ADD_PROPERTY_TYPE(ShowFill ,(false),group,App::Prop_None,"If cut areas must be filled with a hatch pattern or not");
- ADD_PROPERTY_TYPE(LineWidth,(0.35),group,App::Prop_None,"Line width of this view");
+ ADD_PROPERTY_TYPE(LineWidth,(0.25),group,App::Prop_None,"Line width of this view");
ADD_PROPERTY_TYPE(FontSize,(12.0),group,App::Prop_None,"Text size for this view");
+ ADD_PROPERTY_TYPE(CutLineWidth,(0.50),group,App::Prop_None,"Width of cut lines of this view");
+ ADD_PROPERTY_TYPE(JoinArch ,(false),group,App::Prop_None,"If True, walls and structure will be fused by material");
ScaleType.setValue("Custom");
}
@@ -81,7 +83,9 @@ short DrawViewArch::mustExecute() const
ShowHidden.isTouched() ||
ShowFill.isTouched() ||
LineWidth.isTouched() ||
- FontSize.isTouched());
+ FontSize.isTouched() ||
+ CutLineWidth.isTouched() ||
+ JoinArch.isTouched());
}
if ((bool) result) {
return result;
@@ -115,7 +119,9 @@ App::DocumentObjectExecReturn *DrawViewArch::execute(void)
<< ",fontsize=" << FontSize.getValue()
<< ",techdraw=True"
<< ",rotation=" << Rotation.getValue()
- << ",fillSpaces=" << (FillSpaces.getValue() ? "True" : "False");
+ << ",fillSpaces=" << (FillSpaces.getValue() ? "True" : "False")
+ << ",cutlinewidth=" << CutLineWidth.getValue()
+ << ",joinArch=" << (JoinArch.getValue() ? "True" : "False");
Base::Interpreter().runString("import ArchSectionPlane");
Base::Interpreter().runStringArg("svgBody = ArchSectionPlane.getSVG(App.activeDocument().%s %s)",
@@ -145,7 +151,7 @@ std::string DrawViewArch::getSVGTail(void)
void DrawViewArch::Restore(Base::XMLReader &reader)
{
// this is temporary code for backwards compat (within v0.17). can probably be deleted once there are no development
-// fcstd files with old property types in use.
+// fcstd files with old property types in use.
reader.readElement("Properties");
int Cnt = reader.getAttributeAsInteger("Count");
@@ -175,9 +181,9 @@ void DrawViewArch::Restore(Base::XMLReader &reader)
static_cast(schemaProp)->setScope(App::LinkScope::Global);
static_cast(schemaProp)->setValue(link.getValue());
}
-
+
} else {
- // has Source prop isn't PropertyLink or PropertyLinkGlobal!
+ // has Source prop isn't PropertyLink or PropertyLinkGlobal!
Base::Console().Log("DrawViewArch::Restore - old Document Source is weird: %s\n", TypeName);
// no idea
}
diff --git a/src/Mod/TechDraw/App/DrawViewArch.h b/src/Mod/TechDraw/App/DrawViewArch.h
index e430216e34..4d9aa55e66 100644
--- a/src/Mod/TechDraw/App/DrawViewArch.h
+++ b/src/Mod/TechDraw/App/DrawViewArch.h
@@ -50,6 +50,8 @@ public:
App::PropertyBool ShowFill;
App::PropertyFloat LineWidth;
App::PropertyFloat FontSize;
+ App::PropertyFloat CutLineWidth;
+ App::PropertyBool JoinArch;
/** @name methods override Feature */
//@{
@@ -61,7 +63,7 @@ public:
virtual const char* getViewProviderName(void) const override {
return "TechDrawGui::ViewProviderArch";
}
-
+
virtual short mustExecute() const override;
void Restore(Base::XMLReader &reader) override;
@@ -72,7 +74,7 @@ protected:
Base::BoundBox3d bbox;
std::string getSVGHead(void);
std::string getSVGTail(void);
-
+
private:
static const char* RenderModeEnums[];
};
diff --git a/src/Mod/TechDraw/Gui/Command.cpp b/src/Mod/TechDraw/Gui/Command.cpp
index a9f126e75e..a1cce71095 100644
--- a/src/Mod/TechDraw/Gui/Command.cpp
+++ b/src/Mod/TechDraw/Gui/Command.cpp
@@ -79,16 +79,6 @@
using namespace TechDrawGui;
using namespace std;
-bool isArchSection(App::DocumentObject* obj)
-{
- bool result = true;
- App::Property* prop1 = obj->getPropertyByName("Objects");
- App::Property* prop2 = obj->getPropertyByName("OnlySolids");
- if ( (!prop1) || (!prop2) ) {
- result = false;
- }
- return result;
-}
//===========================================================================
// TechDraw_NewPageDef (default template)
@@ -1057,34 +1047,17 @@ void CmdTechDrawArchView::activated(int iMsg)
return;
}
- std::vector objects = getSelection().getObjectsOfType(App::DocumentObject::getClassTypeId());
- if (objects.empty()) {
+ const std::vector objects = getSelection().getObjectsOfType(App::DocumentObject::getClassTypeId());
+ if (objects.size() != 1) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
- QObject::tr("Select at least one object."));
- return;
- }
- int ifound = 0;
- bool found = false;
- for (auto& obj: objects) {
- if (isArchSection(obj)) {
- found = true;
- break;
- }
- ifound++;
- }
- App::DocumentObject* archObj;
- if (found) {
- archObj = objects[ifound];
- } else {
- QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
- QObject::tr("There is no Section Plane in selection."));
+ QObject::tr("Select exactly one object."));
return;
}
std::string PageName = page->getNameInDocument();
std::string FeatName = getUniqueObjectName("ArchView");
- std::string SourceName = archObj->getNameInDocument();
+ std::string SourceName = objects.front()->getNameInDocument();
openCommand("Create ArchView");
doCommand(Doc,"App.activeDocument().addObject('TechDraw::DrawViewArch','%s')",FeatName.c_str());
doCommand(Doc,"App.activeDocument().%s.Source = App.activeDocument().%s",FeatName.c_str(),SourceName.c_str());