public void addNode(StrokeGroup sg)
        {
            /*
             * 1.	如果SKContextDG为空,创建关于s新节点nodeS,算法结束;
             * 2.	创建新节点nodeS,计算笔迹s与前一输入笔迹s’的输入时间差deltTime;
             * 3.	如果deltTime < ThresholdTime,将前一输入笔迹s所对应的节点的tPointer指针指向nodeS;
             * 4.	顺次遍历SKContextDG的历史节点,计算nodeS与历史节点的空间距离dist,根据dist’值判断二者之间的空间关系R;
             * 5.	如果R= ST,在两个节点之间建立空间关联链接,重复步骤4直至遍历完所有节点。
             */

            nodeIndex++;
            SKContextDGNode node = new SKContextDGNode(sg, sg.StartTime, nodeIndex);

            DGNodeList.Add(node);
            node.groupID = sg.groupID;


            double thresholdTime    = 1.2;    //TODO::阈值的确定
            double thresholdSpatial = 1000;   //TODO::阈值的确定


            //空间邻近关系建立
            double dist = -1;

            dist = distance(sg, lastNode.strokeGroup);
            if ((dist > thresholdSpatial) && (!DGHeadList.Contains(node)))
            {
                newHead(node);
            }

            foreach (SKContextDGNode preNode in DGNodeList)
            {
                if (preNode != node)
                {
                    StrokeGroup preSg = null;
                    preSg = preNode.strokeGroup;
                    dist  = distance(sg, preSg);
                    if ((dist < thresholdSpatial) && (!node.sPointer.Contains(preNode)))
                    {
                        node.sPointer.Add(preNode);
                    }
                }
            }


            //时间邻近关系建立
            double delta = (long)((TimeSpan)(sg.StartTime - lastNode.timeStamp)).TotalSeconds;

            if (delta < thresholdTime)
            {
                //时间邻近
                lastNode.tPointer = node;
            }
            else if (!DGHeadList.Contains(node))
            {
                newHead(node);
            }

            lastNode = node;
        }
 public SKContextDGNode(StrokeGroup sg, DateTime time, int nodeIndex)
 {
     strokeGroup = sg;
     timeStamp   = time;
     ID          = nodeIndex;
     tPointer    = null;
 }
Beispiel #3
0
        public void drawBoundingBoxtoTestGrouppingResult()
        {
            //画出ReGroup后的group的包围盒,测试group是否正确

            //统计有多少个group
            SKContextDGNode head     = sketch.sketchContextDG.firstNode;
            SKContextDGNode nextNode = new SKContextDGNode();
            SKContextDGNode curNode  = new SKContextDGNode();

            curNode  = head;
            nextNode = curNode.tPointer;

            int nGroupCount = -1;

            foreach (SKContextDGNode nd in sketch.sketchContextDG.DGNodeList)
            {
                if (nd.groupID > nGroupCount)
                {
                    nGroupCount = nd.groupID;
                }
            }

            Rectangle[] boundingBoxArray;
            boundingBoxArray = new Rectangle[nGroupCount];
            for (int i = 0; i < nGroupCount; i++)
            {
                boundingBoxArray[i] = new Rectangle(1000000, 1000000, -2000000, -2000000);
            }
            int index = 0;

            foreach (SKContextDGNode nd in sketch.sketchContextDG.DGNodeList)
            {
                index = nd.groupID;
                int Left   = boundingBoxArray[index - 1].Left;
                int Right  = boundingBoxArray[index - 1].Right;
                int Top    = boundingBoxArray[index - 1].Top;
                int Bottom = boundingBoxArray[index - 1].Bottom;


                Rectangle rect = nd.strokeGroup.boundingBox;
                Console.Write("node" + nd.ID + "boundingbox:" + "(" + rect.Left + "," + rect.Top + "," + rect.Width + "," + rect.Height + ")");

                if (rect.Left < Left)
                {
                    Left = rect.Left;
                }
                if (rect.Right > Right)
                {
                    Right = rect.Right;
                }
                if (rect.Top < Top)
                {
                    Top = rect.Top;
                }
                if (rect.Bottom > Bottom)
                {
                    Bottom = rect.Bottom;
                }

                boundingBoxArray[index - 1] = new Rectangle(Left, Top, System.Math.Abs(Right - Left), System.Math.Abs(Bottom - Top));
            }

            //绘制出所有的group的包围盒
            Graphics g     = inkPanel.CreateGraphics();
            Pen      mypen = new Pen(Color.Blue);

            for (int i = 0; i < nGroupCount; i++)
            {
                Rectangle rt = new ToolForStroke().InkSpaceToPixelRect(inkPanel.Handle, drawingInk.Renderer, boundingBoxArray[i]);
                g.DrawRectangle(mypen, rt);
                Console.Write("Group" + i + "boundingbox:" + "(" + boundingBoxArray[i].Left + "," + boundingBoxArray[i].Top + "," + boundingBoxArray[i].Width + "," + boundingBoxArray[i].Height + ")");
            }
        }
Beispiel #4
0
        public void sketchReGroupping()
        {
            SKContextDGNode head        = sketch.sketchContextDG.firstNode;
            SKContextDGNode nextNode    = new SKContextDGNode();
            SKContextDGNode curNode     = new SKContextDGNode();
            Sketch          currentpage = sketch.currentpage.Value.content; //当前页

            /*
             * 1.	从SKContextDG中取出输入时间戳最早的节点nodeCur,标记为Head;
             * 2.	从nodeCur出发,找到其tPointer指针所指向的下一个节点nodeNext;
             * 3.	如果当前nodeNext不为空(TT),执行步骤3.1
             */
            curNode = head;


            for (nextNode = curNode.tPointer; ; nextNode = nextNode.tPointer)
            {
                if (nextNode != null) //TT
                {
                    /*
                     * 3.1	对于当前的nodeNext,判断其sPointer指针是否为空;
                     * 3.2	如果sPointer非空(ST),判断sPointer所指节点nodePre是否与nodeCur属于同一个group。
                     *      如果是,则nodeCur和nodeNext之间是强关联类型(TT&ST),nodeNext与nodeCur属于同一个group,
                     *      将nodeNext设为nodeCur,重复步骤2;
                     *      如果nodePre与nodeCur不属于同一个group,则将nodeNext与nodePre归为同一个group,
                     *      将当前nodeCur标记为Tail,从SKContextDG中寻找输入时间戳大于nodeNext的下一个节点记为nodeNext;
                     * 3.3	如果sPointer为空(SF),则nodeCur与nodeNext之间是弱关联II类型(TT&SF),
                     *      视nodeNext为新group的头节点,将其标记为Head,同时,将nodeCur标记为Tail;
                     */
                    int tmp = nextNode.sPointer.Count;
                    if (nextNode.sPointer.Count > 0)
                    {
                        //如果nextnode和curnode空间邻近,则它们属于同一group
                        bool isContain = nextNode.sPointer.Contains(curNode);
                        if (isContain)                          // curNode 和 nextNode是强关联(TT && ST)
                        {
                            nextNode.groupID = curNode.groupID; //属于同一group
                            curNode          = nextNode;
                        }
                        else
                        {
                            //nodeCur与nodeNext之间是弱关联II类型(TT&SF)
                            //检测nextnode和历史node的关系,判断它应该归属于哪一个group
                            //先处理简单情况,nextNode只和属于同一个group的历史节点有空间邻近的关系
                            foreach (SKContextDGNode snode in nextNode.sPointer)
                            {
                                nextNode.groupID = snode.groupID;
                            }
                            curNode = nextNode;
                        }
                    }
                    else//spointer = null 没有与之空间邻近的节点,独立成为一个group
                    {
                        //nodeNext为新group的头节点,将其标记为Head
                        sketch.sketchContextDG.DGHeadList.Add(nextNode);
                        curNode = nextNode;
                    }
                }
                else //TF
                {
                    /*
                     * 4. 如果当前nodeNext为空(TF),从SKContextDG中寻找输入时间戳大于nodeCur节点的最早输入节点,
                     *    令其为nodeNext,
                     *    4.1 如果nodeNext非空,判断其sPointer指针是否为空;
                     *    4.2 如果sPointer非空(ST),判断sPointer所指节点nodePre是否与nodeCur属于同一个group,
                     *        如果是,则nodeCur和nodeNext之间是弱关联I类型(TF&ST),nodeNext与nodeCur属于同一个group,
                     *        将nodeNext设为nodeCur,重复步骤2;
                     *    4.3 如果sPointer为空(SF),则nodeCur与nodeNext之间无关联,视nodeNext为新group的头节点,将其标记为Head,同时,将nodeCur标记为Tail
                     */
                    //先找到nextNdoe节点
                    foreach (SKContextDGNode nd in sketch.sketchContextDG.DGHeadList)
                    {
                        if (nd.timeStamp > curNode.timeStamp)//HeadList都是按序进入的,故只需找到第一个比curNode时间戳大的节点即可
                        {
                            nextNode = nd;
                        }

                        if (nextNode != null)
                        {
                            break;
                        }
                    }
                    if (nextNode == null)
                    {
                        break;
                    }

                    if (nextNode.sPointer != null)
                    {
                        bool isContain = nextNode.sPointer.Contains(curNode);
                        if (isContain)
                        {
                            nextNode.groupID = curNode.groupID;
                            curNode          = nextNode;
                        }
                        else
                        {
                            foreach (SKContextDGNode snode in nextNode.sPointer)
                            {
                                nextNode.groupID = snode.groupID;
                            }
                            curNode = nextNode;
                        }
                    }
                    else
                    {
                        //spointer = null 没有与之空间邻近的节点,独立成为一个group
                        //nodeNext为新group的头节点,将其标记为Head
                        sketch.sketchContextDG.DGHeadList.Add(nextNode);
                        curNode = nextNode;
                    }
                }
            }

            //更新semantic group
            int nGroupCount = -1;

            foreach (SKContextDGNode nd in sketch.sketchContextDG.DGNodeList)
            {
                if (nd.groupID > nGroupCount)
                {
                    nGroupCount = nd.groupID;
                }
            }

            sketch.semanticGroupList.Clear();

            for (int i = 1; i <= nGroupCount; i++)
            {
                SemanticGroup semanticSg = new SemanticGroup();
                sketch.semanticGroupList.Add(semanticSg);
                semanticSg.semanticGroupID = i;
            }

            foreach (SKContextDGNode nn in sketch.sketchContextDG.DGNodeList)
            {
                foreach (SemanticGroup smsg in sketch.semanticGroupList)
                {
                    if ((nn.groupID == smsg.semanticGroupID) && (!smsg.groupList.Contains(nn.strokeGroup)))
                    {
                        smsg.groupList.Add(nn.strokeGroup);
                        smsg.setBoundingBox();
                    }
                }
            }
        }
Beispiel #5
0
        public void addStroke(Stroke stroke)
        {
            List <Stroke> changes   = new List <Stroke>();//需要刷新的stroke
            MyStroke      newstroke = new MyStroke(stroke);

            newstroke.setBoundingBox();                            //YHY-090412
            Sketch currentpage = sketch.currentpage.Value.content; //当前页

            ///线性测试
            if (tool.LinearityTest(newstroke) == Linearity.Line)
            {
                //新增加的stroke是直线
                ///straight-line segment fitting
                foreach (StrokeGroup strokegroup in currentpage.groupList)
                {
                    if (strokegroup.TYPE == GroupType.DEFAULT)
                    {
                        MyStroke mstroke = strokegroup.strokeList.First.Value;
                        if ((tool.DistanceTest(newstroke, mstroke) == TESTRESULT.GROUP) &&
                            (tool.AngleTest(newstroke, mstroke) == TESTRESULT.GROUP))
                        {
                            //通过了距离测试和角度测试
                            strokegroup.addStroke(newstroke);
                            drawingInk.Ink.DeleteStroke(strokegroup.Skeleton);
                            strokegroup.Skeleton = drawingInk.Ink.CreateStroke(strokegroup.SkeletonPoints);
                            strokegroup.Skeleton.DrawingAttributes = this.Skeleton_Attibute;
                            strokegroup.setBoundingBox();//YHY-090412
                            changes.Add(strokegroup.Skeleton);
                            break;
                        }
                    }
                }
                ///如果新增加的笔画没有找到组织,那么将给它单独建一个组
                if (!newstroke.isInGroup)
                {
                    //如果没有通过距离测试和角度测试
                    //Seperate Line
                    StrokeGroup sg = new StrokeGroup(GroupType.DEFAULT);
                    sketch.groupIndex++;
                    sg.groupID = sketch.groupIndex; //YHY-090413 增加一个标志
                    sg.addStroke(newstroke);
                    sg.Skeleton = drawingInk.Ink.CreateStroke(sg.SkeletonPoints);
                    sg.Skeleton.DrawingAttributes = this.Skeleton_Attibute;
                    //YHY-090410
                    sg.GRAPH = Graphic.Line;
                    sg.setBoundingBox();
                    sg.geometry = new G_Line(newstroke.startPoint, newstroke.endPoint);//YHY-090415

                    currentpage.addGroup(sg);

                    //判断新加入的strokegroup代表的图元和历史图元之间的约束关系
                    refreshConstraint(sg);

                    //yhy-090409
                    //将新建的group加入到skechContextDG中去
                    if (sketch.sketchContextDG.isEmpty())
                    {
                        sketch.sketchContextDG.nodeIndex++;
                        SKContextDGNode node = new SKContextDGNode(sg, sg.StartTime, sketch.sketchContextDG.nodeIndex);
                        node.groupID = sg.groupID;
                        sketch.sketchContextDG.newHead(node);
                        sketch.sketchContextDG.firstNode = node;
                        sketch.sketchContextDG.lastNode  = node;
                    }
                    else
                    {
                        sketch.sketchContextDG.addNode(sg);
                    }
                }

                //Groupping: add curve object to strokeGroup and sketch
                //YHY-090409
                ////////////////////////////////////////////////////////////////////////////////
                //YHY-090414
                //Just for test, ReGroup
                //sketchReGroupping();
                //drawBoundingBoxtoTestGrouppingResult();
                //////////////////////////////////////////////////////////////////////////////////


                /* StrokeGroup ngroup = newstroke.group;
                 *
                 * foreach (StrokeGroup group in currentpage.groupList)
                 * {
                 *  if (group == ngroup)
                 *      continue;
                 *
                 *  if (tool.distanceP2P(ngroup.startPoint, group.startPoint) < Threshold_Distance)
                 *  {
                 *      ngroup.startPoint = group.startPoint;
                 *      ngroup.computeSkeletonFromEnds();
                 *  }
                 *  else if (tool.distanceP2P(ngroup.startPoint, group.endPoint) < Threshold_Distance)
                 *  {
                 *      ngroup.startPoint = group.endPoint;
                 *      ngroup.computeSkeletonFromEnds();
                 *  }
                 *  else if (tool.distanceP2P(ngroup.endPoint, group.startPoint) < Threshold_Distance)
                 *  {
                 *      ngroup.endPoint = group.startPoint;
                 *      ngroup.computeSkeletonFromEnds();
                 *  }
                 *  else if (tool.distanceP2P(ngroup.endPoint, group.endPoint) < Threshold_Distance)
                 *  {
                 *      ngroup.endPoint = group.endPoint;
                 *      ngroup.computeSkeletonFromEnds();
                 *  }
                 * }*/
            }

            else if (tool.LinearityTest(newstroke) == Linearity.Curve)
            {
                //如果线性测试的结果是曲线

                //TODO::ToolForStroke.circle(et al).judge function
                //YHY-090408
                //先不考虑曲线补笔等草图特效的问题,假设所有曲线相关的sketch都是单笔的
                //判断是否为circle
                bool isCircle = false;
                isCircle = tool.JudgeCircle(newstroke);

                //YHY-090410
                //创建新的group,先不考虑曲线补笔等情况
                if (!newstroke.isInGroup)
                {
                    StrokeGroup sg = new StrokeGroup(GroupType.DEFAULT);
                    sketch.groupIndex++;
                    sg.groupID = sketch.groupIndex;
                    sg.addStroke(newstroke);
                    sg.setBoundingBox();

                    if (isCircle)
                    {
                        //TODO::暂时统一都认为是圆,以后需要改成椭圆
                        sg.GRAPH = Graphic.Circle;
                        Point  p = new Point();
                        double r;
                        p.X         = sg.boundingBox.Left + sg.boundingBox.Width / 2;
                        p.Y         = sg.boundingBox.Top + sg.boundingBox.Height / 2;
                        r           = System.Math.Min(sg.boundingBox.Height, sg.boundingBox.Width) / 2;
                        sg.geometry = new G_Cricle(p, r);//YHY-090415
                    }
                    else
                    {
                        sg.GRAPH = Graphic.Curve;
                    }

                    //sg.Skeleton = inkpicture.Ink.CreateStroke(sg.SkeletonPoints); //TODO: Get curve skeleton
                    //sg.Skeleton.DrawingAttributes = this.Skeleton_Attibute;
                    currentpage.addGroup(sg);

                    //捕捉约束
                    //判断新加入的strokegroup代表的图元和历史图元之间的约束关系
                    refreshConstraint(sg);


                    //yhy-090409
                    //将新建的group加入到skechContextDG中去
                    if (sketch.sketchContextDG.isEmpty())
                    {
                        sketch.sketchContextDG.nodeIndex++;
                        SKContextDGNode node = new SKContextDGNode(sg, sg.StartTime, sketch.sketchContextDG.nodeIndex);
                        node.groupID = sg.groupID;
                        sketch.sketchContextDG.newHead(node);
                        sketch.sketchContextDG.firstNode = node;
                        sketch.sketchContextDG.lastNode  = node;
                    }
                    else
                    {
                        sketch.sketchContextDG.addNode(sg);
                    }
                }

                //Groupping: add curve object to strokeGroup and sketch
                //YHY-090408
                ////////////////////////////////////////////////////////////////////////////////
                //YHY-090414
                //Just for test, ReGroup
                //   sketchReGroupping();
                //   drawBoundingBoxtoTestGrouppingResult();
                //////////////////////////////////////////////////////////////////////////////////



                //TODO::constraint capture function
                //如果未归为prior group,则需判断新添笔迹(group)与原来笔迹的约束关系
                //YHY-090416
                //判断新添加strokegroup里的图元和其余历史图元之间的关系
            }

            currentpage.addStroke(newstroke);
            ///对纸张进行局部更新
            if (stroke != null)
            {
                inkPanel.Invalidate(tool.InkSpaceToPixelRect(inkPanel.Handle, drawingInk.Renderer, stroke.GetBoundingBox()));
                foreach (Stroke st in changes)
                {
                    inkPanel.Invalidate(tool.InkSpaceToPixelRect(inkPanel.Handle, drawingInk.Renderer, st.GetBoundingBox()));
                }
            }
        }
 public void newHead(SKContextDGNode node)
 {
     DGHeadList.Add(node);
     DGNodeList.Add(node);
 }
 public void setTPoint(SKContextDGNode node)
 {
     tPointer = node;
 }