private void drawLinesFromModelsToAttachmentCenter(LinkType linkType, Vec attachmentCenter, Canvas c)
        {
            var filterLinkViewModel = DataContext as FilterLinkViewModel;

            foreach (
                var incomingModel in
                filterLinkViewModel.FromOperationViewModels.Where(
                    vvm => vvm.OperationModel is IFilterProviderOperationModel).Where(
                    vvm =>
                    filterLinkViewModel.FilterLinkModels.Where(lvm => lvm.LinkType == linkType)
                    .Select(lvm => lvm.FromOperationModel)
                    .Contains(vvm.OperationModel as IFilterProviderOperationModel)))
            {
                var incomingCenter = new Vec(
                    (incomingModel.Position + incomingModel.Size / 2.0).X,
                    (incomingModel.Position + incomingModel.Size / 2.0).Y);
                var incomingRct = new Rct(incomingModel.Position,
                                          new Vec(incomingModel.Size.X, incomingModel.Size.Y));

                var isInverted =
                    filterLinkViewModel.FilterLinkModels.Where(lm => lm.IsInverted)
                    .Select(lm => lm.FromOperationModel)
                    .Contains(incomingModel.OperationModel as IFilterProviderOperationModel);

                var inter =
                    incomingRct.GetLineString()
                    .Intersection(
                        new Windows.Foundation.Point[]
                        { attachmentCenter.GetCoord().GetPt(), incomingCenter.GetCoord().GetPt() }
                        .GetLineString());
                var incomingStart = new Vec();

                if (inter.IsEmpty)
                {
                    incomingStart = incomingCenter;
                }
                else
                {
                    incomingStart = new Vec(inter.Centroid.X, inter.Centroid.Y);
                }
                var distanceVec = attachmentCenter - incomingStart;
                if (distanceVec.Length > 0)
                {
                    var cutOff = distanceVec.Normalized() * (distanceVec.Length - _attachmentRectHalfSize);

                    /* var l1 = new Line();
                     * l1.X1 = incomingStart.X;
                     * l1.Y1 = incomingStart.Y;
                     * l1.X2 = incomingStart.X + cutOff.X;
                     * l1.Y2 = incomingStart.Y + cutOff.Y;
                     * if (
                     *   filterLinkViewModel.FilterLinkModels.Where(lm => lm.IsInverted)
                     *       .Select(lm => lm.FromOperationModel)
                     *       .Contains(incomingModel.OperationModel as IFilterProviderOperationModel))
                     *   l1.StrokeDashArray = new DoubleCollection {2};
                     * l1.Stroke = new SolidColorBrush(Colors.Red);
                     * l1.StrokeThickness = 2;
                     * c.Children.Add(l1);*/


                    var n           = distanceVec.Perp().Normalized();
                    var trianglePos = distanceVec.Normalized() * (distanceVec.Length * 0.3) + incomingStart;


                    var start = incomingStart + distanceVec.Normalized() * 4;
                    var end   = incomingStart + cutOff;

                    var thinkness   = 4;
                    var arrowWidth  = 8;
                    var arrowLength = 20;
                    var poly        = new Polygon();

                    if (!isInverted)
                    {
                        poly.Points.Add((start - (n * thinkness / 2.0)).GetWindowsPoint());
                        poly.Points.Add((start + (n * thinkness / 2.0)).GetWindowsPoint());
                    }
                    poly.Points.Add((trianglePos + (n * thinkness / 2.0)).GetWindowsPoint());
                    poly.Points.Add((trianglePos + (n * ((thinkness / 2.0) + arrowWidth))).GetWindowsPoint());
                    poly.Points.Add((trianglePos + (distanceVec.Normalized() * arrowLength) + (n * ((thinkness / 2.0)))).GetWindowsPoint());
                    if (!isInverted)
                    {
                        poly.Points.Add((end + (n * thinkness / 2.0)).GetWindowsPoint());
                        poly.Points.Add((end - (n * thinkness / 2.0)).GetWindowsPoint());
                    }
                    poly.Points.Add((trianglePos + (distanceVec.Normalized() * arrowLength) - (n * ((thinkness / 2.0)))).GetWindowsPoint());
                    poly.Points.Add((trianglePos - (n * ((thinkness / 2.0) + arrowWidth))).GetWindowsPoint());
                    poly.Points.Add((trianglePos - (n * thinkness / 2.0)).GetWindowsPoint());
                    if (!isInverted)
                    {
                        poly.Points.Add((start - (n * thinkness / 2.0)).GetWindowsPoint());
                    }

                    /*poly.Points.Add(new Windows.Foundation.Point(trianglePos.X + n.X*8, trianglePos.Y + n.Y*8));
                    *  poly.Points.Add(new Windows.Foundation.Point(trianglePos.X - n.X*8, trianglePos.Y - n.Y*8));
                    *  poly.Points.Add(new Windows.Foundation.Point(trianglePos.X + distanceVec.Normalized().X*20,
                    *   trianglePos.Y + distanceVec.Normalized().Y*20));
                    *  poly.Points.Add(new Windows.Foundation.Point(trianglePos.X + n.X*8, trianglePos.Y + n.Y*8));*/
                    poly.Fill            = _lightBrush;
                    poly.StrokeThickness = 1;
                    //poly.StrokeDashArray = new DoubleCollection { 2 };
                    poly.Stroke = _backgroundBrush;
                    c.Children.Add(poly);

                    if (isInverted)
                    {
                        drawDashedLine(start, trianglePos, n, thinkness, c);
                        drawDashedLine(trianglePos + (distanceVec.Normalized() * arrowLength), end, n, thinkness, c);
                    }

                    if (!_visualizationViewModelCenterGeometries.ContainsKey(incomingModel))
                    {
                        _visualizationViewModelCenterGeometries.Add(incomingModel,
                                                                    poly.Points.GetPolygon().Buffer(3));
                        _visualizationViewModelGeometries.Add(incomingModel,
                                                              new Windows.Foundation.Point[]
                                                              { incomingStart.GetCoord().GetPt(), (incomingStart + cutOff).GetCoord().GetPt() }
                                                              .GetLineString());
                    }
                }
            }
        }
        private Vec updateAttachmentCenter(LinkType linkType, Canvas canvas)
        {
            var filterLinkViewModel = DataContext as FilterLinkViewModel;

            var destinationRct = new Rct(filterLinkViewModel.ToOperationViewModel.Position,
                                         new Vec(filterLinkViewModel.ToOperationViewModel.Size.X, filterLinkViewModel.ToOperationViewModel.Size.Y));
            var destinationGeom = destinationRct.GetLineString();

            var midPoints   = new List <Pt>();
            var sourceCount = 0;

            foreach (
                var from in
                filterLinkViewModel.FromOperationViewModels.Where(
                    vvm => vvm.OperationModel is IFilterProviderOperationModel).Where(
                    vvm =>
                    filterLinkViewModel.FilterLinkModels.Where(lvm => lvm.LinkType == linkType)
                    .Select(lvm => lvm.FromOperationModel)
                    .Contains(vvm.OperationModel as IFilterProviderOperationModel)))
            {
                sourceCount++;
                var fromCenterToCenter = new Windows.Foundation.Point[]
                {
                    filterLinkViewModel.ToOperationViewModel.Position +
                    filterLinkViewModel.ToOperationViewModel.Size / 2.0,
                    from.Position + from.Size / 2.0
                }.GetLineString();
                var sourceRct = new Rct(from.Position,
                                        new Vec(from.Size.X, from.Size.Y)).GetLineString();
                var interPtSource      = sourceRct.Intersection(fromCenterToCenter);
                var interPtDestination = destinationGeom.Intersection(fromCenterToCenter);

                var midPoint = new Vec();
                if (interPtDestination.IsEmpty || interPtSource.IsEmpty)
                {
                    midPoint = (filterLinkViewModel.ToOperationViewModel.Position +
                                filterLinkViewModel.ToOperationViewModel.Size / 2.0 +
                                (from.Position + from.Size / 2.0)).GetVec() / 2.0;
                }
                else
                {
                    midPoint = (new Vec(interPtSource.Centroid.X, interPtSource.Centroid.Y) +
                                new Vec(interPtDestination.Centroid.X, interPtDestination.Centroid.Y)) / 2.0;
                }
                midPoints.Add(new Pt(midPoint.X, midPoint.Y));
            }

            if (sourceCount == 0)
            {
                if (linkType == LinkType.Brush)
                {
                    return(new Vec(
                               destinationRct.Left + _attachmentRectHalfSize,
                               destinationRct.Bottom + _attachmentRectHalfSize - 2));
                }
                else if (linkType == LinkType.Filter)
                {
                    return(new Vec(
                               destinationRct.Right - _attachmentRectHalfSize,
                               destinationRct.Bottom + _attachmentRectHalfSize - 2));
                }
            }

            var tempAttachment = midPoints.Aggregate((p1, p2) => p1 + p2).GetVec() / midPoints.Count;
            var destinationVec = new Vec(
                (filterLinkViewModel.ToOperationViewModel.Position + filterLinkViewModel.ToOperationViewModel.Size / 2.0)
                .X,
                (filterLinkViewModel.ToOperationViewModel.Position + filterLinkViewModel.ToOperationViewModel.Size / 2.0)
                .Y);
            var inter =
                destinationGeom.Intersection(
                    new Windows.Foundation.Point[]
                    { tempAttachment.GetCoord().GetPt(), destinationVec.GetCoord().GetPt() }.GetLineString());
            var attachmentCenter = new Vec();

            if (inter.IsEmpty)
            {
                var dirVec = tempAttachment - destinationVec;
                dirVec  = dirVec.Normal() * 40000;
                dirVec += tempAttachment;
                inter   =
                    destinationGeom.Intersection(
                        new Windows.Foundation.Point[] { dirVec.GetCoord().GetPt(), destinationVec.GetCoord().GetPt() }
                        .GetLineString());
                attachmentCenter = new Vec(inter.Centroid.X, inter.Centroid.Y);
            }
            else
            {
                attachmentCenter = new Vec(inter.Centroid.X, inter.Centroid.Y);
            }

            var attachmentLocation = getAttachmentLocation(destinationRct, attachmentCenter);

            // left
            if (attachmentLocation == AttachmentLocation.Left)
            {
                attachmentCenter = new Vec(
                    attachmentCenter.X - _attachmentRectHalfSize + 2,
                    Math.Min(Math.Max(attachmentCenter.Y, destinationRct.Top + _attachmentRectHalfSize),
                             destinationRct.Bottom - _attachmentRectHalfSize));
            }
            // right
            else if (attachmentLocation == AttachmentLocation.Right)
            {
                attachmentCenter = new Vec(
                    attachmentCenter.X + _attachmentRectHalfSize - 2,
                    Math.Min(Math.Max(attachmentCenter.Y, destinationRct.Top + _attachmentRectHalfSize),
                             destinationRct.Bottom - _attachmentRectHalfSize));
            }
            // top
            else if (attachmentLocation == AttachmentLocation.Top)
            {
                attachmentCenter = new Vec(
                    Math.Min(Math.Max(attachmentCenter.X, destinationRct.Left + _attachmentRectHalfSize),
                             destinationRct.Right - _attachmentRectHalfSize),
                    attachmentCenter.Y - _attachmentRectHalfSize + 2);
            }
            // bottom
            else if (attachmentLocation == AttachmentLocation.Bottom)
            {
                attachmentCenter = new Vec(
                    Math.Min(Math.Max(attachmentCenter.X, destinationRct.Left + _attachmentRectHalfSize),
                             destinationRct.Right - _attachmentRectHalfSize),
                    attachmentCenter.Y + _attachmentRectHalfSize - 2);
            }

            return(attachmentCenter);
        }