/// <summary>
        /// <para>For calculating with the parameter slots in instances w/o affecting the component and its parameters.</para>
        /// <para>Performed recursively in case the sub-components contain calculations themselves.</para>
        /// </summary>
        /// <param name="_container"></param>
        internal void ExecuteCalculationChainWoArtefacts(FlNetElement _container)
        {
            if (_container == null)
            {
                return;
            }
            GeometricRelationship instance = this.R2GInstances.FirstOrDefault(x => x.InstanceNWElementID == _container.ID);

            if (instance == null)
            {
                return;
            }

            // populate the parameter values
            if (instance.InstanceParamValues == null || instance.InstanceParamValues.Count == 0)
            {
                this.UpdateInstanceIn(_container, new Point(0, 0), false);
            }

            // recursion
            this.ExecuteCalculationChainForInstance(instance);

            // result transfer params -> size, if necessary
            instance.ApplySizeTransferSettings();
        }
        internal void RemoveInstance(FlNetElement _container)
        {
            if (_container == null)
            {
                return;
            }

            // check for the proper type of geometric relationship
            if (this.R2GMainState.Type != Relation2GeomType.CONTAINED_IN && this.R2GMainState.Type != Relation2GeomType.CONNECTS)
            {
                return;
            }

            // check if the user has writing access
            ComponentManagerType user = ComponentManagerType.ADMINISTRATOR;

            if (this.Factory != null)
            {
                bool success = this.RecordWritingAccess(this.Factory.Caller);
                user = this.Factory.Caller;
                if (!success)
                {
                    return;
                }
            }
            else
            {
                return;
            }

            // if there is only one geometric relationship -> reset it
            if (this.R2GInstances.Count == 1 && this.R2GInstances[0].InstanceNWElementID == _container.ID)
            {
                this.R2GInstances[0].Reset();
                return;
            }

            // otherwise, just remove
            List <bool> to_retain = new List <bool>();

            for (int i = 0; i < this.R2GInstances.Count; i++)
            {
                if (this.R2GInstances[i].InstanceNWElementID == _container.ID)
                {
                    to_retain.Add(false);
                    this.RemovePlacementBasedReferencesToInstanceFromOtherComponents(this.R2GInstances[i]);
                }
                else
                {
                    to_retain.Add(true);
                }
            }

            // includes handling the case of the first (main) relationship being removed
            this.UpdateGeometricRelationships(to_retain, null, user);
            // re-calculate the cumulative values
            this.UpdateCumulativeValuesFromInstances();
        }
        internal GeometricRelationship UpdateInstanceIn(FlNetElement _container, Point _offset, bool _reset)
        {
            if (_container == null)
            {
                return(null);
            }

            GeometricRelationship gr = this.R2GInstances.FirstOrDefault(x => x.InstanceNWElementID == _container.ID);

            if (gr == null)
            {
                return(null);
            }
            if (gr.InstanceNWElementID != _container.ID)
            {
                return(null);
            }

            // assemble parameters to pass to the instance
            Dictionary <string, double> param_slots = this.ExtractParameterValues();

            // size is a special case !!!
            param_slots[Parameter.Parameter.RP_HEIGHT_MIN] = gr.InstanceSize[0];
            param_slots[Parameter.Parameter.RP_WIDTH_MIN]  = gr.InstanceSize[1];
            param_slots[Parameter.Parameter.RP_LENGTH_MIN] = gr.InstanceSize[2];
            param_slots[Parameter.Parameter.RP_HEIGHT_MAX] = gr.InstanceSize[3];
            param_slots[Parameter.Parameter.RP_WIDTH_MAX]  = gr.InstanceSize[4];
            param_slots[Parameter.Parameter.RP_LENGTH_MAX] = gr.InstanceSize[5];

            // controlled reset
            if (gr.InstanceParamValues == null)
            {
                gr.InstanceParamValues = param_slots;
                return(gr);
            }

            if (_reset)
            {
                gr.InstanceParamValues = param_slots;
                gr.UpdatePositionFrom(_container, _offset, Component.SCALE_PIXEL_TO_M);
                return(gr);
            }
            else
            {
                foreach (var entry in param_slots)
                {
                    if (!(gr.InstanceParamValues.ContainsKey(entry.Key)))
                    {
                        gr.InstanceParamValues.Add(entry.Key, entry.Value);
                    }
                }
                gr.ApplySizeTransferSettings();
            }

            return(gr);
        }
        internal GeometricRelationship GetInstanceIn(FlNetElement _container)
        {
            if (_container == null)
            {
                return(null);
            }
            if (this.R2GInstances == null)
            {
                return(null);
            }

            return(this.R2GInstances.FirstOrDefault(x => x.InstanceNWElementID == _container.ID));
        }
        internal void UpdateInstancePositionIn(FlNetElement _container, Point _offset)
        {
            if (_container == null)
            {
                return;
            }

            GeometricRelationship gr = this.R2GInstances.FirstOrDefault(x => x.InstanceNWElementID == _container.ID);

            if (gr == null)
            {
                return;
            }
            if (gr.InstanceNWElementID != _container.ID)
            {
                return;
            }

            gr.UpdatePositionFrom(_container, new Point(0, 0), Component.SCALE_PIXEL_TO_M);
        }
        /// <summary>
        /// <para>Returns the value, as a formatted string, in the parameter slot of the instance placed in the NW element.</para>
        /// <para>The parameter can be contained in this component or ANY of its sub-components.</para>
        /// </summary>
        /// <param name="_container"></param>
        /// <param name="_param_suffix"></param>
        /// <returns></returns>
        internal string GetParamValueOfInstance(FlNetElement _container, string _param_suffix)
        {
            if (_container == null)
            {
                return(string.Empty);
            }
            if (string.IsNullOrEmpty(_param_suffix))
            {
                return(string.Empty);
            }

            Parameter.Parameter p = this.GetFirstParamBySuffix(_param_suffix);
            if (p == null)
            {
                return(string.Empty);
            }

            string info = string.Empty;

            foreach (GeometricRelationship gr in this.R2GInstances)
            {
                if (gr.InstanceNWElementID != _container.ID)
                {
                    continue;
                }

                if (gr.InstanceParamValues == null || gr.InstanceParamValues.Count == 0)
                {
                    this.UpdateInstanceIn(_container, new Point(0, 0), false);
                }

                if (gr.InstanceParamValues.ContainsKey(p.Name))
                {
                    info = Parameter.Parameter.ValueToString(gr.InstanceParamValues[p.Name], "F2");
                }

                return(info);
            }

            return(info);
        }
        /// <summary>
        /// Called when placing a component in a NW element. It creates a new instance of the component.
        /// </summary>
        /// <param name="_container"></param>
        internal void CreateInstance(FlNetElement _container)
        {
            if (_container == null)
            {
                return;
            }

            // check for the proper type of geometric relationship
            if (this.R2GMainState.Type != Relation2GeomType.CONTAINED_IN && this.R2GMainState.Type != Relation2GeomType.CONNECTS)
            {
                return;
            }

            // check if the user has writing access
            if (this.Factory != null)
            {
                bool success = this.RecordWritingAccess(this.Factory.Caller);
                if (!success)
                {
                    return;
                }
            }
            else
            {
                return;
            }

            // check for duplicates
            foreach (GeometricRelationship gr in this.R2GInstances)
            {
                if (gr.InstanceNWElementID == _container.ID)
                {
                    return;
                }
            }

            // check for previous instancing:
            bool first_instancing = (this.R2GInstances.Count == 1 && this.R2GInstances[0].InstanceNWElementID < 0);

            // add an automatically generated sub-component containing the size parameters
            // add an automatically generated sub-component containing the cumulative parameters
            if (!this.ContainsValidAutoSubcomponentForSize())
            {
                this.AutoAddSubcomponentForSize();
            }
            if (!this.ContainsValidAutoSubcomponentForCumulation())
            {
                this.AutoAddSubcomponentForCumulation();
            }

            // assemble parameters to pass to the instance
            Dictionary <string, double> param_slots = this.ExtractParameterValues();

            // if there has not been any assignment so far, use the first and only GeometricRelationship
            if (first_instancing)
            {
                this.R2GInstances[0].PlaceInFlowNetworkElement(_container, new Point(0, 0), Component.SCALE_PIXEL_TO_M, new List <double> {
                    0, 0, 0, 0, 0, 0
                }, param_slots);
            }
            else
            {
                this.R2GInstances.Add(GeometricRelationship.CreateAndPlaceInFlowNetworkElement(_container, new Point(0, 0), Component.SCALE_PIXEL_TO_M, param_slots));
            }

            this.UpdateCumulativeValuesFromInstances(); // for the instance counter
        }