About the Reducing schematic nodes and computing a cumulative attribute via a schematic rule Sample
[C#]
NodeReductionRule.cs
using ESRI.ArcGIS;
using ESRI.ArcGIS.ADF.CATIDs;
using ESRI.ArcGIS.Schematic;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.esriSystem;
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
namespace CustomRulesCS
{
[ClassInterface(ClassInterfaceType.None)]
[Guid(NodeReductionRule.GUID)]
[ProgId(NodeReductionRule.PROGID)]
public class NodeReductionRule : ISchematicRule, ISchematicRuleDesign
{
public const string GUID = "A6CB9935-AE08-46FB-9850-77C2B4E7C6A9";
public const string PROGID = "CustomRulesCS.NodeReductionRule";
// Register/unregister categories for this class
#region "Component Category Registration"
[System.Runtime.InteropServices.ComRegisterFunction()]
public static void Register(string CLSID)
{
SchematicRules.Register(CLSID);
}
[System.Runtime.InteropServices.ComUnregisterFunction()]
public static void Unregister(string CLSID)
{
SchematicRules.Unregister(CLSID);
}
#endregion
private ISchematicDiagramClass m_diagramClass;
private string m_description = "Reduction Node Rule - Report cumulative value C#";
private string m_lengthAttributeName;
private string m_reducedNodeClassName;
private string m_superspanLinkClassName;
private string m_linkAttributeName;
private bool m_keepVertices = true;
private bool m_linkAttribute = false;
#region NodeReductionRule interface
public NodeReductionRule()
{
}
~NodeReductionRule()
{
m_diagramClass = null;
}
public bool LinkAttribute
{
get
{
return m_linkAttribute;
}
set
{
m_linkAttribute = value;
}
}
public string LinkAttributeName
{
get
{
return m_linkAttributeName;
}
set
{
m_linkAttributeName = value;
}
}
public bool KeepVertices
{
get
{
return m_keepVertices;
}
set
{
m_keepVertices = value;
}
}
public string LengthAttributeName
{
get
{
return m_lengthAttributeName;
}
set
{
m_lengthAttributeName = value;
}
}
public string ReducedNodeClassName
{
get
{
return m_reducedNodeClassName;
}
set
{
m_reducedNodeClassName = value;
}
}
public string SuperpanLinkClassName
{
get
{
return m_superspanLinkClassName;
}
set
{
m_superspanLinkClassName = value;
}
}
#endregion
#region ISchematicRule Members
public void Alter(ISchematicDiagramClass schematicDiagramClass, ESRI.ArcGIS.esriSystem.IPropertySet propertySet)
{
m_diagramClass = schematicDiagramClass;
try
{
m_description = propertySet.GetProperty("DESCRIPTION").ToString();
}
catch { }
try
{
m_reducedNodeClassName = propertySet.GetProperty("REDUCEDNODECLASS").ToString();
}
catch { }
try
{
m_superspanLinkClassName = propertySet.GetProperty("SUPERSPANLINKCLASS").ToString();
}
catch { }
try
{
m_lengthAttributeName = propertySet.GetProperty("LENGTHATTRIBUTENAME").ToString();
}
catch { }
try
{
m_keepVertices = (bool)propertySet.GetProperty("KEEPVERTICES");
}
catch { }
try
{
m_linkAttribute = (bool)propertySet.GetProperty("LINKATTRIBUTE");
}
catch { }
try
{
m_linkAttributeName = propertySet.GetProperty("LINKATTRIBUTENAME").ToString();
}
catch { }
}
public void Apply(ISchematicInMemoryDiagram inMemoryDiagram, ESRI.ArcGIS.esriSystem.ITrackCancel cancelTracker)
{
if (m_reducedNodeClassName == "" || inMemoryDiagram == null) return;
// initialize the schematic rules helper
ISchematicRulesHelper rulesHelper = new SchematicRulesHelperClass();
rulesHelper.InitHelper(inMemoryDiagram);
rulesHelper.KeepVertices = m_keepVertices;
////////////////////////
// get the feature classes processed by the rule
ISchematicDiagramClass diagramClass = null;
try
{
diagramClass = inMemoryDiagram.SchematicDiagramClass;
}
catch { }
if (diagramClass == null) return;
ISchematicDataset schematicDataset = null;
try
{
schematicDataset = diagramClass.SchematicDataset;
}
catch { }
ISchematicElementClassContainer elementclassContainer = (ISchematicElementClassContainer)schematicDataset;
if (elementclassContainer == null) return;
ISchematicElementClass elementClassReducedNode = null;
elementClassReducedNode = elementclassContainer.GetSchematicElementClass(m_reducedNodeClassName);
ISchematicElementClass elementClassSuperspan = null;
elementClassSuperspan = elementclassContainer.GetSchematicElementClass(m_superspanLinkClassName);
if (elementClassSuperspan == null || elementClassReducedNode == null) return;
ISchematicInMemoryFeatureClassContainer featureClassContainer = (ISchematicInMemoryFeatureClassContainer)inMemoryDiagram;
if (featureClassContainer == null) return;
ISchematicInMemoryFeatureClass superspanLinkClass = featureClassContainer.GetSchematicInMemoryFeatureClass(elementClassSuperspan);
//
/////////////////////////
// fetch the superspan spatial reference
IGeoDataset geoDataset = (IGeoDataset)superspanLinkClass;
ISpatialReference spatialRef = null;
if (geoDataset != null) spatialRef = geoDataset.SpatialReference;
if (spatialRef == null) return;
// Retrieve the schematic in memory feature nodes to reduce
System.Collections.Generic.Dictionary<string, ISchematicInMemoryFeature> colSchfeatureNode = new Dictionary<string, ISchematicInMemoryFeature>();
// get all feature of parent node class
IEnumSchematicInMemoryFeature enumSchematicInMemoryFeature = inMemoryDiagram.GetSchematicInMemoryFeaturesByClass(elementClassReducedNode);
// retain only the nodes of degree two
RetainNodesDegreeTwo(enumSchematicInMemoryFeature, colSchfeatureNode, rulesHelper); // there would be inserted a SQL query to also filter by attributes
IProgressor msgProgressor = null;
if (cancelTracker != null)
{
msgProgressor = cancelTracker.Progressor;
IStepProgressor stepProgressor = (IStepProgressor)msgProgressor;
if (stepProgressor != null)
{
stepProgressor.MinRange = 0;
stepProgressor.MaxRange = colSchfeatureNode.Count;
stepProgressor.StepValue = 1;
stepProgressor.Position = 0;
stepProgressor.Message = m_description;
cancelTracker.Reset();
cancelTracker.Progressor = msgProgressor;
stepProgressor.Show();
}
}
ISchematicInMemoryFeature schFeatureToReduce;
foreach (KeyValuePair<string, ISchematicInMemoryFeature> kvp in colSchfeatureNode)
{
if (cancelTracker != null)
if (cancelTracker.Continue() == false)
break;
schFeatureToReduce = colSchfeatureNode[kvp.Key];
if (schFeatureToReduce != null) ReduceNode(rulesHelper, superspanLinkClass, spatialRef, schFeatureToReduce);
}
// release memory
colSchfeatureNode.Clear();
colSchfeatureNode = null;
rulesHelper = null;
}
public ESRI.ArcGIS.esriSystem.UID ClassID
{
get
{
ESRI.ArcGIS.esriSystem.UID ruleID = new ESRI.ArcGIS.esriSystem.UID();
ruleID.Value = PROGID;
return ruleID;
}
}
public string Description
{
get
{
return m_description;
}
set
{
m_description = value;
}
}
string ISchematicRule.Description
{
get { return m_description; }
}
public string Name
{
get
{
return "Node Reduction Rule C#";
}
}
public ESRI.ArcGIS.esriSystem.IPropertySet PropertySet
{
get
{
ESRI.ArcGIS.esriSystem.IPropertySet propertySet = new ESRI.ArcGIS.esriSystem.PropertySet();
propertySet.SetProperty("DESCRIPTION", m_description);
propertySet.SetProperty("REDUCEDNODECLASS", m_reducedNodeClassName);
propertySet.SetProperty("SUPERSPANLINKCLASS", m_superspanLinkClassName);
propertySet.SetProperty("KEEPVERTICES", m_keepVertices);
propertySet.SetProperty("LENGTHATTRIBUTENAME", m_lengthAttributeName);
propertySet.SetProperty("LINKATTRIBUTE", m_linkAttribute);
propertySet.SetProperty("LINKATTRIBUTENAME", m_linkAttributeName);
return propertySet;
}
}
ISchematicDiagramClass ISchematicRule.SchematicDiagramClass
{
get { return m_diagramClass; }
}
#endregion
#region ISchematicRuleDesign Members
public void Detach()
{
m_diagramClass = null;
}
ESRI.ArcGIS.esriSystem.IPropertySet ISchematicRuleDesign.PropertySet
{
set
{
m_description = value.GetProperty("DESCRIPTION").ToString();
m_reducedNodeClassName = value.GetProperty("REDUCEDNODECLASS").ToString();
m_superspanLinkClassName = value.GetProperty("SUPERSPANLINKCLASS").ToString();
m_keepVertices = (bool)value.GetProperty("KEEPVERTICES");
m_lengthAttributeName = value.GetProperty("LENGTHATTRIBUTENAME").ToString();
m_linkAttribute = (bool)value.GetProperty("LINKATTRIBUTE");
m_linkAttributeName = value.GetProperty("LINKATTRIBUTENAME").ToString();
}
}
ISchematicDiagramClass ISchematicRuleDesign.SchematicDiagramClass
{
get
{
return m_diagramClass;
}
set
{
m_diagramClass = value;
}
}
#endregion ISchematicRuleDesign
#region private methods
private void ReduceNode(ISchematicRulesHelper rulesHelper, ISchematicInMemoryFeatureClass superspanLinkClass , ISpatialReference spatialRef, ISchematicInMemoryFeature schFeatureToReduce)
{
if (schFeatureToReduce.Displayed == false || rulesHelper == null || spatialRef == null)
return;
// get the two connected links
IEnumSchematicInMemoryFeature enumLink = rulesHelper.GetDisplayedIncidentLinks((ISchematicInMemoryFeatureNode)schFeatureToReduce, esriSchematicEndPointType.esriSchematicOriginOrExtremityNode);
if (enumLink == null || enumLink.Count != 2)
return;
enumLink.Reset();
ISchematicInMemoryFeature schFeat1 = enumLink.Next();
ISchematicInMemoryFeature schFeat2 = enumLink.Next();
ISchematicInMemoryFeatureLink schLink1 = (ISchematicInMemoryFeatureLink)schFeat1;
ISchematicInMemoryFeatureLink schLink2 = (ISchematicInMemoryFeatureLink)schFeat2;
if (schLink1 == null || schLink2 == null) return;
ISchematicInMemoryFeature schFeatureSuperspan = null;
ISchematicInMemoryFeature schFeatureTmp = null;
ISchematicInMemoryFeatureNode schNodeToReduce = (ISchematicInMemoryFeatureNode)schFeatureToReduce;
ISchematicInMemoryFeatureNode schFromNode;
ISchematicInMemoryFeatureNode schToNode;
int iFromPort;
int iToPort;
IGeometry superspanGeometry;
if (schLink2.FromNode == schNodeToReduce)
{
superspanGeometry = BuildLinkGeometry(schLink1, schNodeToReduce, schLink2, rulesHelper);
if (schLink1.ToNode == schNodeToReduce)
{
schFromNode = schLink1.FromNode;
iFromPort = schLink1.FromPort;
}
else
{
schFromNode = schLink1.ToNode;
iFromPort = schLink1.ToPort;
}
schToNode = schLink2.ToNode;
iToPort = schLink2.ToPort;
}
else
{
superspanGeometry = BuildLinkGeometry(schLink2, schNodeToReduce, schLink1, rulesHelper);
schFromNode = schLink2.FromNode;
iFromPort = schLink2.FromPort;
if (schLink1.FromNode == schNodeToReduce)
{
schToNode = schLink1.ToNode;
iToPort = schLink1.ToPort;
}
else
{
schToNode = schLink1.FromNode;
iToPort = schLink1.FromPort;
}
}
if (superspanGeometry != null)
superspanGeometry.SpatialReference = spatialRef;
// find a unique name for the superspan
string strFromName = schFromNode.Name;
string strtoName = schToNode.Name;
string strName;
long lCount = 1;
while (schFeatureSuperspan == null)
{
strName = strFromName + ";" + strtoName + ";" + lCount.ToString();
if (strName.Length >= 128)
break; // too long a name
try
{
schFeatureTmp = rulesHelper.AlterLink(superspanLinkClass, strName, null, superspanGeometry, -2, -2,
strFromName, strtoName, esriFlowDirection.esriFDWithFlow, iFromPort, iToPort);
}
catch
{
schFeatureTmp = null;
}
if (schFeatureTmp == null)
continue;
// valid new feature
schFeatureSuperspan = schFeatureTmp;
}
// last chance for a unique name
lCount = 1;
while (schFeatureSuperspan == null)
{
strName = schNodeToReduce.Name + ";" + lCount.ToString();
if (strName.Length >= 128)
break; // too long a name
try
{
schFeatureTmp = rulesHelper.AlterLink(superspanLinkClass, strName, null, superspanGeometry, -2, -2,
strFromName, strtoName, esriFlowDirection.esriFDWithFlow, iFromPort, iToPort);
}
catch
{
schFeatureTmp = null;
}
if (schFeatureTmp == null)
continue;
// valid new feature
schFeatureSuperspan = schFeatureTmp;
}
if (schFeatureSuperspan == null)
return; // cannot find a unique name
// otherwise report the cumulated length of the reduced links to the superspan
ReportCumulativeValues(schFeat1, schFeat2, schFeatureSuperspan);
// report the associations on the superspan link
rulesHelper.ReportAssociations(schFeatureToReduce, schFeatureSuperspan);
rulesHelper.ReportAssociations(schFeat1, schFeatureSuperspan);
rulesHelper.ReportAssociations(schFeat2, schFeatureSuperspan);
// hide the reduced objects
rulesHelper.HideFeature(schFeatureToReduce);
rulesHelper.HideFeature(schFeat1);
rulesHelper.HideFeature(schFeat2);
}
private void ReportCumulativeValues(ISchematicInMemoryFeature schFeat1, ISchematicInMemoryFeature schFeat2, ISchematicInMemoryFeature schTargetFeat)
{
if (schFeat1 == null || schFeat2 == null || schTargetFeat == null)
return;
// assume the attribute field name is the same on every schematic feature link classes
IFields linkFields = schFeat1.Fields;
int iIndex = linkFields.FindField(m_lengthAttributeName);
if (iIndex < 0) return; // attribute field does not exist
object value1 = schFeat1.get_Value(iIndex);
linkFields = schFeat2.Fields;
iIndex = linkFields.FindField(m_lengthAttributeName);
if (iIndex < 0) return; // attribute field does not exist
object value2 = schFeat2.get_Value(iIndex);
double dValue1 = 0;
double dValue2 = 0;
if (!DBNull.Value.Equals(value1))
{
try
{
dValue1 = Convert.ToDouble(value1);
}
catch { }
}
if (!DBNull.Value.Equals(value2))
{
try
{
dValue2 = Convert.ToDouble(value2);
}
catch{ }
}
// assume the values to be numeric
double dlength = dValue1 + dValue2;
linkFields = schTargetFeat.Fields;
iIndex = linkFields.FindField(m_lengthAttributeName);
if (iIndex < 0) return; // attribute field does not exist
schTargetFeat.set_Value(iIndex, dlength);
}
private IGeometry BuildLinkGeometry(ISchematicInMemoryFeatureLink schLink1, ISchematicInMemoryFeatureNode schNodeToReduce, ISchematicInMemoryFeatureLink schLink2, ISchematicRulesHelper rulesHelper)
{
if (schLink1 == null || schLink2 == null || schNodeToReduce == null || rulesHelper == null)
return null;
if (m_keepVertices == false)
return null; // no geometry
Polyline newPoly = new Polyline();
IPolyline polyLink1 = rulesHelper.GetLinkPoints(schLink1, (schLink1.FromNode == schNodeToReduce));
IPolyline polyLink2 = rulesHelper.GetLinkPoints(schLink2, (schLink2.ToNode == schNodeToReduce));
IPoint nodePt = rulesHelper.GetNodePoint(schNodeToReduce);
IPoint Pt;
IPointCollection newPts = (IPointCollection)newPoly;
IPointCollection link1Pts = (IPointCollection)polyLink1;
IPointCollection link2Pts = (IPointCollection)polyLink2;
int Count = link1Pts.PointCount;
int i;
for (i = 0; i < Count - 1; i++)
{
Pt = link1Pts.get_Point(i);
newPts.AddPoint(Pt);
}
newPts.AddPoint(nodePt);
Count = link2Pts.PointCount;
for (i = 1; i < Count; i++)
{
Pt = link2Pts.get_Point(i);
newPts.AddPoint(Pt);
}
IGeometry buildGeometry = (IGeometry)newPoly;
return buildGeometry;
}
private void RetainNodesDegreeTwo(IEnumSchematicInMemoryFeature enumInMemoryFeature,
Dictionary<string, ISchematicInMemoryFeature> colSchfeatureNode, ISchematicRulesHelper ruleHelper)
{
ISchematicInMemoryFeature schInMemoryfeature;
if (ruleHelper == null) return;
enumInMemoryFeature.Reset();
schInMemoryfeature = enumInMemoryFeature.Next();
while (schInMemoryfeature != null)
{
if (schInMemoryfeature.Displayed)
{
IEnumSchematicInMemoryFeature enumLinks = ruleHelper.GetDisplayedIncidentLinks((ISchematicInMemoryFeatureNode)schInMemoryfeature, esriSchematicEndPointType.esriSchematicOriginOrExtremityNode);
if (enumLinks != null && enumLinks.Count == 2)
{
// Valid degree two node
if (!colSchfeatureNode.ContainsKey(schInMemoryfeature.Name))
{
if (!LinkAttribute)
colSchfeatureNode.Add(schInMemoryfeature.Name, schInMemoryfeature);
else
{
if(SameIncidentLinkAttributeValue(enumLinks, LinkAttributeName, ruleHelper))
colSchfeatureNode.Add(schInMemoryfeature.Name, schInMemoryfeature);
}
}
}
}
schInMemoryfeature = enumInMemoryFeature.Next();
}
}
private bool SameIncidentLinkAttributeValue(IEnumSchematicInMemoryFeature enumInMemoryLinks, string attributeName, ISchematicRulesHelper ruleHelper)
{
ISchematicInMemoryFeature inMemoryFeature = null;
enumInMemoryLinks.Reset();
bool bFirstVariant = true;
object vPreviousValue = null;
object vCurrentValue = null;
inMemoryFeature = enumInMemoryLinks.Next();
while (inMemoryFeature != null)
{
// Do not take account the link if the link is not displayed
//
// Search for an attribute with the given name
//
ISchematicElementClass schematicElementClass;
schematicElementClass = inMemoryFeature.SchematicElementClass;
ISchematicAttributeContainer attributeContainer = (ISchematicAttributeContainer)schematicElementClass;
ISchematicAttribute schematicAttribute = null;
if (attributeContainer != null)
schematicAttribute = attributeContainer.GetSchematicAttribute(attributeName, true);
if (schematicAttribute != null)
{
ISchematicObject schematicObject = (ISchematicObject)inMemoryFeature;
vCurrentValue = schematicAttribute.GetValue(schematicObject);
}
else
{
// If schematic attribute not existing ==> find a field in the associated feature
IObject iObject = null;
ISchematicInMemoryFeaturePrimaryAssociation primaryAssociation = (ISchematicInMemoryFeaturePrimaryAssociation)inMemoryFeature;
if (primaryAssociation != null)
iObject = primaryAssociation.AssociatedObject;
IRow row = (IRow)iObject;
int fieldIndex = 0;
if (row != null)
{
IFields fields = row.Fields;
if (fields != null)
fieldIndex = fields.FindField(attributeName);
}
if (fieldIndex > 0)
{
vCurrentValue = row.get_Value(fieldIndex);
if (DBNull.Value.Equals(vCurrentValue))
return false;
}
else
return false;
}
if (bFirstVariant)
{
vPreviousValue = vCurrentValue;
bFirstVariant = false;
}
else
{
// Compare PreviousValue and CurrentValue
if (vPreviousValue.GetType() != vCurrentValue.GetType())
return false;
if (DBNull.Value.Equals(vPreviousValue) || DBNull.Value.Equals(vCurrentValue))
return false;
if (vPreviousValue.GetType().FullName is System.String)//Speciale Case for string.
{
string str1 = (string)vPreviousValue;
string str2 = (string)vCurrentValue;
if( string.Compare(str1, str2, true) != 0)
return false;
}
else if (vPreviousValue != vCurrentValue)// == or != operator compare for Variant match the right type.
return false;
}
inMemoryFeature = enumInMemoryLinks.Next();
}
return true;
}
}
#endregion
}
[Visual Basic .NET]
NodeReductionRule.vb
Option Strict On
Imports System
Imports System.Collections.Generic
Imports System.Runtime.InteropServices
Imports ESRI.ArcGIS
Imports ESRI.ArcGIS.ADF.CATIDs
Imports ESRI.ArcGIS.Schematic
Imports ESRI.ArcGIS.Geometry
Imports ESRI.ArcGIS.Geodatabase
Imports esriSystem = ESRI.ArcGIS.esriSystem
<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)> _
<System.Runtime.InteropServices.Guid(NodeReductionRule.GUID)> _
<System.Runtime.InteropServices.ProgId(NodeReductionRule.PROGID)> _
Public Class NodeReductionRule
Implements ESRI.ArcGIS.Schematic.ISchematicRule
Implements ESRI.ArcGIS.Schematic.ISchematicRuleDesign
Public Const GUID As String = "5CA4A4C9-CBDF-4B4E-8932-53A962C92C22"
Public Const PROGID As String = "CustomRulesVB.NodeReductionRule"
' Register/unregister categories for this class
#Region "Component Category Registration"
<System.Runtime.InteropServices.ComRegisterFunction()> _
Shared Sub Register(ByVal CLSID As String)
ESRI.ArcGIS.ADF.CATIDs.SchematicRules.Register(CLSID)
End Sub
<System.Runtime.InteropServices.ComUnregisterFunction()> _
Shared Sub Unregister(ByVal CLSID As String)
ESRI.ArcGIS.ADF.CATIDs.SchematicRules.Unregister(CLSID)
End Sub
#End Region
Private m_diagramClass As ESRI.ArcGIS.Schematic.ISchematicDiagramClass
Private m_reducedNodeClassName As String
Private m_lengthAttributeName As String
Private m_superspanLinkClassName As String
Private m_linkAttributeName As String
Private m_description As String = "Reduction Node Rule - Report cumulative value VBNet"
Private m_keepVertices As Boolean = True
Private m_linkAttribute As Boolean = False
#Region "NodeReductionRule Members"
Public Sub New()
End Sub
Protected Overrides Sub Finalize()
m_diagramClass = Nothing
MyBase.Finalize()
End Sub
Public Property LinkAttribute() As Boolean
Get
Return m_linkAttribute
End Get
Set(ByVal value As Boolean)
m_linkAttribute = value
End Set
End Property
Public Property LinkAttributeName() As String
Get
Return m_linkAttributeName
End Get
Set(ByVal value As String)
m_linkAttributeName = value
End Set
End Property
Public Property KeepVertices() As Boolean
Get
Return m_keepVertices
End Get
Set(ByVal value As Boolean)
m_keepVertices = value
End Set
End Property
Public Property ReducedNodeClassName() As String
Get
Return m_reducedNodeClassName
End Get
Set(ByVal value As String)
m_reducedNodeClassName = value
End Set
End Property
Public Property LengthAttributeName() As String
Get
Return m_lengthAttributeName
End Get
Set(ByVal value As String)
m_lengthAttributeName = value
End Set
End Property
Public Property SuperpanLinkClassName() As String
Get
Return m_superspanLinkClassName
End Get
Set(ByVal value As String)
m_superspanLinkClassName = value
End Set
End Property
#End Region
#Region "ISchematicRule Members"
Public Sub Alter(ByVal schematicDiagramClass As ESRI.ArcGIS.Schematic.ISchematicDiagramClass, ByVal propertySet As ESRI.ArcGIS.esriSystem.IPropertySet) Implements ESRI.ArcGIS.Schematic.ISchematicRule.Alter
m_diagramClass = schematicDiagramClass
Try
m_description = propertySet.GetProperty("DESCRIPTION").ToString()
Catch
End Try
Try
m_reducedNodeClassName = propertySet.GetProperty("REDUCEDNODECLASS").ToString()
Catch
End Try
Try
m_superspanLinkClassName = propertySet.GetProperty("SUPERSPANLINKCLASS").ToString()
Catch
End Try
Try
m_keepVertices = CBool(propertySet.GetProperty("KEEPVERTICES"))
Catch
End Try
Try
m_lengthAttributeName = propertySet.GetProperty("LENGTHATTRIBUTENAME").ToString()
Catch
End Try
Try
m_linkAttribute = CBool(propertySet.GetProperty("LINKATTRIBUTE"))
Catch
End Try
Try
m_linkAttributeName = propertySet.GetProperty("LINKATTRIBUTENAME").ToString()
Catch
End Try
End Sub
Public Sub Apply(ByVal inMemoryDiagram As ESRI.ArcGIS.Schematic.ISchematicInMemoryDiagram, Optional ByVal cancelTracker As ESRI.ArcGIS.esriSystem.ITrackCancel = Nothing) Implements ESRI.ArcGIS.Schematic.ISchematicRule.Apply
Dim rulesHelper As ISchematicRulesHelper = New SchematicRulesHelper()
Dim diagramClass As ISchematicDiagramClass = Nothing
Dim elementClassReducedNode As ISchematicElementClass = Nothing
Dim elementClassSuperspan As ISchematicElementClass = Nothing
Dim elementClassContainer As ISchematicElementClassContainer
Dim superspanLinkClass As ISchematicInMemoryFeatureClass
Dim schematicDataset As ISchematicDataset
Dim featureClassContainer As ISchematicInMemoryFeatureClassContainer
Dim geoDataset As IGeoDataset
Dim spatialRef As ISpatialReference = Nothing
Dim colSchfeatureNode As New System.Collections.Generic.Dictionary(Of String, ISchematicInMemoryFeature)
Dim kvp As KeyValuePair(Of String, ISchematicInMemoryFeature)
Dim enumSchematicInMemoryFeature As IEnumSchematicInMemoryFeature = Nothing
Dim msgProgressor As ESRI.ArcGIS.esriSystem.IProgressor = Nothing
Dim stepProgressor As ESRI.ArcGIS.esriSystem.IStepProgressor
Dim schFeatureToReduce As ISchematicInMemoryFeature
If (m_reducedNodeClassName Is Nothing Or inMemoryDiagram Is Nothing) Then Return
' initialize the schematic rules helper
rulesHelper.InitHelper(inMemoryDiagram)
rulesHelper.KeepVertices = m_keepVertices
'Get the feature classes processed by the rule
Try
diagramClass = inMemoryDiagram.SchematicDiagramClass
Catch
End Try
If (diagramClass Is Nothing) Then Return
Try
schematicDataset = diagramClass.SchematicDataset
Catch
schematicDataset = Nothing
End Try
elementClassContainer = CType(schematicDataset, ISchematicElementClassContainer)
If (elementClassContainer Is Nothing) Then Return
elementClassReducedNode = elementClassContainer.GetSchematicElementClass(m_reducedNodeClassName)
elementClassSuperspan = elementClassContainer.GetSchematicElementClass(m_superspanLinkClassName)
If (elementClassSuperspan Is Nothing Or elementClassReducedNode Is Nothing) Then Return
featureClassContainer = CType(inMemoryDiagram, ISchematicInMemoryFeatureClassContainer)
If (featureClassContainer Is Nothing) Then Return
superspanLinkClass = featureClassContainer.GetSchematicInMemoryFeatureClass(elementClassSuperspan)
' fetch the superspan spatial reference
geoDataset = CType(superspanLinkClass, IGeoDataset)
If (geoDataset IsNot Nothing) Then spatialRef = geoDataset.SpatialReference
If (spatialRef Is Nothing) Then Return
' Retrieve the schematic in memory feature nodes to reduce
' get all feature of parent node class
enumSchematicInMemoryFeature = inMemoryDiagram.GetSchematicInMemoryFeaturesByClass(elementClassReducedNode)
' retain only the nodes of degree two
RetainNodesDegreeTwo(enumSchematicInMemoryFeature, colSchfeatureNode, rulesHelper) ' there would be inserted a SQL query to also filter by attributes
If (cancelTracker IsNot Nothing) Then
msgProgressor = cancelTracker.Progressor
stepProgressor = CType(msgProgressor, ESRI.ArcGIS.esriSystem.IStepProgressor)
If (stepProgressor IsNot Nothing) Then
stepProgressor.MinRange = 0
stepProgressor.MaxRange = colSchfeatureNode.Count
stepProgressor.StepValue = 1
stepProgressor.Position = 0
stepProgressor.Message = m_description
cancelTracker.Reset()
cancelTracker.Progressor = msgProgressor
stepProgressor.Show()
End If
End If
For Each kvp In colSchfeatureNode
If (cancelTracker IsNot Nothing) Then
If (cancelTracker.Continue() = False) Then Exit For
End If
schFeatureToReduce = CType(colSchfeatureNode(kvp.Key), ISchematicInMemoryFeature)
If (schFeatureToReduce IsNot Nothing) Then ReduceNode(rulesHelper, superspanLinkClass, spatialRef, schFeatureToReduce)
Next
colSchfeatureNode.Clear()
colSchfeatureNode = Nothing
rulesHelper = Nothing
End Sub
Public ReadOnly Property ClassID() As ESRI.ArcGIS.esriSystem.UID Implements ESRI.ArcGIS.Schematic.ISchematicRule.ClassID
Get
Dim ruleID As esriSystem.UID = New esriSystem.UID()
ruleID.Value = PROGID
Return ruleID
End Get
End Property
Public ReadOnly Property Description1() As String Implements ESRI.ArcGIS.Schematic.ISchematicRule.Description
Get
Return m_description
End Get
End Property
Public Property Description() As String
Get
Return m_description
End Get
Set(ByVal value As String)
m_description = value
End Set
End Property
Public ReadOnly Property Name() As String Implements ESRI.ArcGIS.Schematic.ISchematicRule.Name
Get
Return "Node Reduction Rule VBNet"
End Get
End Property
Public ReadOnly Property PropertySet() As ESRI.ArcGIS.esriSystem.IPropertySet Implements ESRI.ArcGIS.Schematic.ISchematicRule.PropertySet
Get
Dim propSet As esriSystem.IPropertySet = New esriSystem.PropertySet()
propSet.SetProperty("DESCRIPTION", m_description)
propSet.SetProperty("REDUCEDNODECLASS", m_reducedNodeClassName)
propSet.SetProperty("SUPERSPANLINKCLASS", m_superspanLinkClassName)
propSet.SetProperty("KEEPVERTICES", m_keepVertices)
propSet.SetProperty("LENGTHATTRIBUTENAME", m_lengthAttributeName)
propSet.SetProperty("LINKATTRIBUTENAME", m_linkAttributeName)
propSet.SetProperty("LINKATTRIBUTE", m_linkAttribute)
Return propSet
End Get
End Property
Public ReadOnly Property SchematicDiagramClass() As ESRI.ArcGIS.Schematic.ISchematicDiagramClass Implements ESRI.ArcGIS.Schematic.ISchematicRule.SchematicDiagramClass
Get
Return m_diagramClass
End Get
End Property
#End Region
#Region "ISchematicRuleDesign Members"
Public Sub Detach() Implements ESRI.ArcGIS.Schematic.ISchematicRuleDesign.Detach
m_diagramClass = Nothing
End Sub
Public WriteOnly Property PropertySet1() As ESRI.ArcGIS.esriSystem.IPropertySet Implements ESRI.ArcGIS.Schematic.ISchematicRuleDesign.PropertySet
Set(ByVal value As ESRI.ArcGIS.esriSystem.IPropertySet)
m_description = value.GetProperty("DESCRIPTION").ToString()
m_reducedNodeClassName = value.GetProperty("REDUCEDNODECLASS").ToString()
m_superspanLinkClassName = value.GetProperty("SUPERSPANLINKCLASS").ToString()
m_keepVertices = CBool(value.GetProperty("KEEPVERTICES"))
m_lengthAttributeName = value.GetProperty("LENGTHATTRIBUTENAME").ToString()
m_linkAttribute = CBool(value.GetProperty("LINKATTRIBUTE"))
m_linkAttributeName = value.GetProperty("LINKATTRIBUTENAME").ToString()
End Set
End Property
Public Property SchematicDiagramClass1() As ESRI.ArcGIS.Schematic.ISchematicDiagramClass Implements ESRI.ArcGIS.Schematic.ISchematicRuleDesign.SchematicDiagramClass
Get
Return m_diagramClass
End Get
Set(ByVal value As ESRI.ArcGIS.Schematic.ISchematicDiagramClass)
m_diagramClass = value
End Set
End Property
#End Region
#Region "Node Reduction Rule private Members"
Private Sub ReduceNode(ByVal rulesHelper As ISchematicRulesHelper, ByVal superspanLinkClass As ISchematicInMemoryFeatureClass, ByVal spatialRef As ISpatialReference, ByVal schFeatureToReduce As ISchematicInMemoryFeature)
Dim enumLink As IEnumSchematicInMemoryFeature
Dim schFeatureSuperspan As ISchematicInMemoryFeature = Nothing
Dim schFeatureTmp As ISchematicInMemoryFeature = Nothing
Dim schFeat1 As ISchematicInMemoryFeature = Nothing
Dim schFeat2 As ISchematicInMemoryFeature = Nothing
Dim schLink1 As ISchematicInMemoryFeatureLink = Nothing
Dim schLink2 As ISchematicInMemoryFeatureLink = Nothing
Dim schNodeToReduce As ISchematicInMemoryFeatureNode = Nothing
Dim schFromNode As ISchematicInMemoryFeatureNode = Nothing
Dim schToNode As ISchematicInMemoryFeatureNode = Nothing
Dim superspanGeometry As IGeometry = Nothing
Dim iFromPort As Integer
Dim iToPort As Integer
Dim lCount As Long = 1
Dim strFromName As String
Dim strtoName As String
Dim strName As String
If (schFeatureToReduce.Displayed = False Or rulesHelper Is Nothing Or spatialRef Is Nothing) Then Exit Sub
' get the two connected links
enumLink = rulesHelper.GetDisplayedIncidentLinks(CType(schFeatureToReduce, ISchematicInMemoryFeatureNode), esriSchematicEndPointType.esriSchematicOriginOrExtremityNode)
If (enumLink Is Nothing Or enumLink.Count <> 2) Then Exit Sub
enumLink.Reset()
schFeat1 = enumLink.Next()
schFeat2 = enumLink.Next()
schLink1 = CType(schFeat1, ISchematicInMemoryFeatureLink)
schLink2 = CType(schFeat2, ISchematicInMemoryFeatureLink)
If (schLink1 Is Nothing Or schLink2 Is Nothing) Then Exit Sub
schNodeToReduce = CType(schFeatureToReduce, ISchematicInMemoryFeatureNode)
If (schLink2.FromNode Is schNodeToReduce) Then
superspanGeometry = BuildLinkGeometry(schLink1, schNodeToReduce, schLink2, rulesHelper)
If (schLink1.ToNode Is schNodeToReduce) Then
schFromNode = schLink1.FromNode
iFromPort = schLink1.FromPort
Else
schFromNode = schLink1.ToNode
iFromPort = schLink1.ToPort
End If
schToNode = schLink2.ToNode
iToPort = schLink2.ToPort
Else
superspanGeometry = BuildLinkGeometry(schLink2, schNodeToReduce, schLink1, rulesHelper)
schFromNode = schLink2.FromNode
iFromPort = schLink2.FromPort
If (schLink1.FromNode Is schNodeToReduce) Then
schToNode = schLink1.ToNode
iToPort = schLink1.ToPort
Else
schToNode = schLink1.FromNode
iToPort = schLink1.FromPort
End If
End If
If (superspanGeometry IsNot Nothing) Then superspanGeometry.SpatialReference = spatialRef
' find a unique name for the superspan
strFromName = schFromNode.Name
strtoName = schToNode.Name
lCount = 1
While (schFeatureSuperspan Is Nothing)
strName = strFromName + ";" + strtoName + ";" + lCount.ToString()
If (strName.Length >= 128) Then Exit While ' too long a name
Try
schFeatureTmp = rulesHelper.AlterLink(superspanLinkClass, strName, Nothing, superspanGeometry, -2, -2,
strFromName, strtoName, esriFlowDirection.esriFDWithFlow, iFromPort, iToPort)
Catch
schFeatureTmp = Nothing
End Try
If (schFeatureTmp IsNot Nothing) Then
' valid new feature
schFeatureSuperspan = schFeatureTmp
Exit While
End If
End While
' last chance for a unique name
lCount = 1
While (schFeatureSuperspan Is Nothing)
strName = schNodeToReduce.Name + ";" + lCount.ToString()
If (strName.Length >= 128) Then Exit While ' too long a name
Try
schFeatureTmp = rulesHelper.AlterLink(superspanLinkClass, strName, Nothing, superspanGeometry, -2, -2,
strFromName, strtoName, esriFlowDirection.esriFDWithFlow, iFromPort, iToPort)
Catch
schFeatureTmp = Nothing
End Try
If (schFeatureTmp IsNot Nothing) Then
' valid new feature
schFeatureSuperspan = schFeatureTmp
Exit While
End If
End While
If (schFeatureSuperspan Is Nothing) Then Exit Sub ' cannot find a unique name
' otherwise report the cumulated length of the reduced links to the superspan
ReportCumulativeValues(schFeat1, schFeat2, schFeatureSuperspan)
' report the associations on the superspan link
rulesHelper.ReportAssociations(schFeatureToReduce, schFeatureSuperspan)
rulesHelper.ReportAssociations(schFeat1, schFeatureSuperspan)
rulesHelper.ReportAssociations(schFeat2, schFeatureSuperspan)
' hide the reduced objects
rulesHelper.HideFeature(schFeatureToReduce)
rulesHelper.HideFeature(schFeat1)
rulesHelper.HideFeature(schFeat2)
End Sub
Private Sub ReportCumulativeValues(ByVal schFeat1 As ISchematicInMemoryFeature, ByVal schFeat2 As ISchematicInMemoryFeature, ByVal schTargetFeat As ISchematicInMemoryFeature)
Dim linkFields As IFields = Nothing
Dim value1 As Object
Dim value2 As Object
Dim iIndex As Integer
Dim dLength As Double
Dim dValue1 As Double = 0
Dim dValue2 As Double = 0
If (schFeat1 Is Nothing Or schFeat2 Is Nothing Or schTargetFeat Is Nothing) Then Exit Sub
' assume the attribute field name is the same on every schematic feature link classes
linkFields = schFeat1.Fields
iIndex = linkFields.FindField(m_lengthAttributeName)
If (iIndex < 0) Then Exit Sub ' attribute field does not exist
value1 = schFeat1.Value(iIndex)
linkFields = schFeat2.Fields
iIndex = linkFields.FindField(m_lengthAttributeName)
If (iIndex < 0) Then Exit Sub ' attribute field does not exist
value2 = schFeat2.Value(iIndex)
If (Not DBNull.Value.Equals(value1)) Then
dValue1 = CDbl(value1)
End If
If (Not DBNull.Value.Equals(value2)) Then
dValue2 = CDbl(value2)
End If
' assume the values to be numeric
dLength = dValue1 + dValue2
linkFields = schTargetFeat.Fields
iIndex = linkFields.FindField(m_lengthAttributeName)
If (iIndex < 0) Then Exit Sub ' attribute field does not exist
schTargetFeat.Value(iIndex) = dLength
End Sub
Private Function BuildLinkGeometry(ByVal schLink1 As ISchematicInMemoryFeatureLink, ByVal schNodeToReduce As ISchematicInMemoryFeatureNode, ByVal schLink2 As ISchematicInMemoryFeatureLink, ByVal rulesHelper As ISchematicRulesHelper) As IGeometry
If (schLink1 Is Nothing Or schLink2 Is Nothing Or schNodeToReduce Is Nothing Or rulesHelper Is Nothing) Then Return Nothing
If (m_keepVertices = False) Then Return Nothing 'no geometry
Dim polyLink1 As IPolyline = Nothing
Dim polyLink2 As IPolyline = Nothing
Dim nodePt As IPoint = Nothing
Dim Pt As IPoint = Nothing
Dim newPts As IPointCollection = Nothing
Dim link1Pts As IPointCollection = Nothing
Dim link2Pts As IPointCollection = Nothing
Dim buildGeometry As IGeometry = New Polyline()
Dim iCount As Integer
Dim i As Integer
polyLink1 = rulesHelper.GetLinkPoints(schLink1, (schLink1.FromNode Is schNodeToReduce))
polyLink2 = rulesHelper.GetLinkPoints(schLink2, (schLink2.ToNode Is schNodeToReduce))
nodePt = rulesHelper.GetNodePoint(schNodeToReduce)
newPts = CType(buildGeometry, IPointCollection)
link1Pts = CType(polyLink1, IPointCollection)
link2Pts = CType(polyLink2, IPointCollection)
iCount = link1Pts.PointCount
For i = 0 To iCount - 2 Step 1
Pt = link1Pts.Point(i)
newPts.AddPoint(Pt)
Next
newPts.AddPoint(nodePt)
iCount = link2Pts.PointCount
For i = 1 To iCount - 1 Step 1
Pt = link2Pts.Point(i)
newPts.AddPoint(Pt)
Next
Return buildGeometry
End Function
Private Sub RetainNodesDegreeTwo(ByRef enumInMemoryFeature As IEnumSchematicInMemoryFeature, ByRef colSchfeatureNode As System.Collections.Generic.Dictionary(Of String, ISchematicInMemoryFeature), ByVal ruleHelper As ISchematicRulesHelper)
Dim schInMemoryfeature As ISchematicInMemoryFeature = Nothing
enumInMemoryFeature.Reset()
schInMemoryfeature = enumInMemoryFeature.Next()
While (schInMemoryfeature IsNot Nothing)
If (schInMemoryfeature.Displayed) Then
Dim schInMemoryNode As ISchematicInMemoryFeatureNode = Nothing
schInMemoryNode = CType(schInMemoryfeature, ISchematicInMemoryFeatureNode)
Dim enumLinks As IEnumSchematicInMemoryFeature = Nothing
enumLinks = ruleHelper.GetDisplayedIncidentLinks(schInMemoryNode, esriSchematicEndPointType.esriSchematicOriginOrExtremityNode)
If (enumLinks IsNot Nothing And enumLinks.Count = 2) Then
' Valid degree two node
If (Not colSchfeatureNode.ContainsKey(schInMemoryfeature.Name)) Then
If (Not LinkAttribute) Then
colSchfeatureNode.Add(schInMemoryfeature.Name, schInMemoryfeature)
ElseIf (SameIncidentLinkAttributeValue(enumLinks, LinkAttributeName, ruleHelper)) Then
colSchfeatureNode.Add(schInMemoryfeature.Name, schInMemoryfeature)
End If
End If
End If
End If
schInMemoryfeature = enumInMemoryFeature.Next()
End While
End Sub
Private Function SameIncidentLinkAttributeValue(ByVal enumInMemoryLinks As IEnumSchematicInMemoryFeature, ByVal attributeName As String, ByVal ruleHelper As ISchematicRulesHelper) As Boolean
Dim inMemoryFeature As ISchematicInMemoryFeature = Nothing
Dim bFirstVariant As Boolean = True
Dim vPreviousValue As Object = Nothing
Dim vCurrentValue As Object = Nothing
enumInMemoryLinks.Reset()
inMemoryFeature = enumInMemoryLinks.Next()
While (inMemoryFeature IsNot Nothing)
' Do not take account the link if the link is not displayed
' Search for an attribute with the given name
Dim schematicElementClass As ISchematicElementClass
schematicElementClass = inMemoryFeature.SchematicElementClass
Dim attributeContainer As ISchematicAttributeContainer = CType(schematicElementClass, ISchematicAttributeContainer)
Dim schematicAttribute As ISchematicAttribute = Nothing
If (attributeContainer IsNot Nothing) Then
schematicAttribute = attributeContainer.GetSchematicAttribute(attributeName, True)
End If
If (schematicAttribute IsNot Nothing) Then
Dim schematicObject As ISchematicObject = CType(inMemoryFeature, ISchematicObject)
vCurrentValue = schematicAttribute.GetValue(schematicObject)
Else
'If schematic attribute not existing ==> find a field in the associated feature
Dim iObject As IObject = Nothing
Dim primaryAssociation As ISchematicInMemoryFeaturePrimaryAssociation = CType(inMemoryFeature, ISchematicInMemoryFeaturePrimaryAssociation)
If (primaryAssociation IsNot Nothing) Then
iObject = primaryAssociation.AssociatedObject
End If
Dim row As IRow = CType(iObject, IRow)
Dim fieldIndex As Integer = 0
If (row IsNot Nothing) Then
Dim fields As IFields = row.Fields
If (fields IsNot Nothing) Then fieldIndex = fields.FindField(attributeName)
End If
If (fieldIndex > 0) Then
vCurrentValue = row.Value(fieldIndex)
If (DBNull.Value.Equals(vCurrentValue)) Then Return False
Else
Return False
End If
End If
If (bFirstVariant) Then
vPreviousValue = vCurrentValue
bFirstVariant = False
Else
' Compare PreviousValue and CurrentValue
If (vPreviousValue.GetType() IsNot vCurrentValue.GetType()) Then Return False
If (DBNull.Value.Equals(vPreviousValue) Or DBNull.Value.Equals(vCurrentValue)) Then Return False
If (TypeOf (vPreviousValue.GetType().FullName) Is System.String) Then 'Speciale Case for string.
Dim str1 As String = vPreviousValue.ToString()
Dim str2 As String = vCurrentValue.ToString()
If (String.Compare(str1, str2, True) <> 0) Then Return False
ElseIf (Not vPreviousValue.Equals(vCurrentValue)) Then
Return False ' == or != operator compare for Variant match the right type.
End If
End If
inMemoryFeature = enumInMemoryLinks.Next()
End While
Return True
End Function
#End Region
End Class