Beispiel #1
0
        // 被上面函数引用,用来计算手臂的slicer
        private void GetMostMatchedArmSlicer(ref SlicerRecord chestshoul, SlicerRecord Aend, ref SlicerRecord nArm0)
        {
            double       target        = Math.Abs(Aend.radius - nArm0.radius);
            SlicerRecord ret           = null;
            int          currLoopTimes = 100;
            Vector3d     rootCentre    = Aend.slicerCenter;
            double       currInterval  = (rootCentre - nArm0.slicerCenter).Length() / currLoopTimes;

            for (int i = 0; i < currLoopTimes; i++)
            {
                Vector3d refSkeNode     = rootCentre + ((double)i / currLoopTimes) * (nArm0.slicerCenter - rootCentre);
                Vector3d refNodeNormal0 = ((double)i / currLoopTimes) * Aend.slicerNormal +
                                          (1 - (double)i / currLoopTimes) * nArm0.slicerNormal;
                Plane        nodePlane0 = new Plane(refSkeNode, refNodeNormal0);
                SlicerRecord t1         = new SlicerRecord(segMesh, nodePlane0);
                TrickForSegment.BuildNewArmTopslicer(chestshoul, t1, out SlicerRecord torsoIntp);
                if (torsoIntp != null && Math.Abs(Aend.radius - torsoIntp.radius) < target)
                {
                    target = Math.Abs(Aend.radius - torsoIntp.radius);
                    ret    = torsoIntp;
                }
            }
            if (ret != null)
            {
                nArm0 = ret;
            }
        }
Beispiel #2
0
        /// <summary>
        /// 环切切片得到角度均匀的环片
        /// </summary>
        /// <param name="s"></param>
        /// <param name="n"></param>
        /// <returns></returns>
        public List <SlicerRecordUniform> RadialSlicerCut(List <SlicerRecord> s, int n)
        {
            int[]    nSeq  = Enumerable.Range(0, n).ToArray();
            double[] piSeq = Enumerable.Repeat <double>(2 * Math.PI, n).ToArray();
            double[] phi   = piSeq.Zip(nSeq, (x, y) => x * y / n).ToArray();
            List <SlicerRecordUniform> ret = new List <SlicerRecordUniform>();

            for (int i = 0; i < s.Count; i++)
            {
                List <Vector3d> tempnp   = new List <Vector3d>();
                SlicerRecord    tempSR   = s[i];
                Vector3d        plcen    = s[i].slicerCenter;
                Vector3d        slicernv = s[i].slicerNormal;
                // 这里的参考旋转轴需要实时改变,针对不同的模型,与下面的radiaRay变量搭配
                // 可以使用3个轴的,也可以使用8个象限的旋转轴
                Vector3d radialSpinAx = new Vector3d(0, 1, 0);
                double   cost         = radialSpinAx.Dot(slicernv); // cost is cos(t)
                //List<Vector3d> debugNormal = new List<Vector3d>();
                for (int k = 0; k < n; k++)
                {
                    double maxDist = double.MinValue;

                    Vector3d radialRay         = new Vector3d(Math.Cos(phi[k]), 0, Math.Sin(phi[k]));
                    Vector3d radialPlaneNormal = new Vector3d(Math.Cos(phi[k]), 0, -Math.Sin(phi[k]));
                    Vector3d newRay            = Vector3d.RotationRodriguesMethod(radialSpinAx.Cross(slicernv), radialRay, cost).Normalize();
                    Plane    halfCutPlane      = new Plane(plcen, newRay.Cross(slicernv));
                    //debugNormal.Add(newRay);
                    //int dir = slicernv.Dot(new Vector3d(0, 1, 0)) > 0 ? 1 : -1;
                    // 这个阶段是为了找到隔断的点
                    Vector3d maxOutP = new Vector3d();
                    for (int j = 0; j < tempSR.lineList.Count; j++)
                    {
                        Vector3d p1 = tempSR.pointInfoList[tempSR.lineList[j].p1].p;
                        Vector3d p2 = tempSR.pointInfoList[tempSR.lineList[j].p2].p;
                        double   tempP1Planedist = PointPlaneDistance(p1, halfCutPlane);
                        double   tempP2Planedist = PointPlaneDistance(p2, halfCutPlane);
                        if (tempP2Planedist * tempP1Planedist > 0)
                        {
                            continue;                                         // 检测交叉
                        }
                        Vector3d outP = (p1 * Math.Abs(tempP2Planedist) + p2 * Math.Abs(tempP1Planedist)) / (Math.Abs(tempP1Planedist) + Math.Abs(tempP2Planedist));
                        if ((outP - plcen).Dot(newRay) < 0)
                        {
                            continue;                                   // 检测射线方向
                        }
                        if ((outP - plcen).Length() > maxDist)
                        {
                            maxDist = (outP - plcen).Length();
                            maxOutP = outP;
                        }
                    }
                    if (maxOutP != (Vector3d) new Vector3d())
                    {
                        tempnp.Add(maxOutP);
                    }
                }
                ret.Add(new SlicerRecordUniform(tempnp, plcen));
            }
            return(ret);
        }
Beispiel #3
0
        private void AddtionCreateSlicer(List <SlicerRecord>[] bodySlicerGroup)  // 增加大腿与手臂
        {
            SlicerRecord bottomTorso = bodySlicerGroup[(int)bodypart.Torso].Last();
            SlicerRecord leg0top     = bodySlicerGroup[(int)bodypart.Leg_0].First();
            SlicerRecord leg1top     = bodySlicerGroup[(int)bodypart.Leg_1].First();

            SlicerRecord chestshoul = TrickForSegment.chestshoul;

            TrickForSegment.BuildSeperateLimbSlicer(leg0top, leg1top, out SlicerRecord nLeg0, out SlicerRecord nLeg1);

            // Arm
            SlicerRecord arm0top = bodySlicerGroup[(int)bodypart.Arm_0].First();
            SlicerRecord arm1top = bodySlicerGroup[(int)bodypart.Arm_1].First();

            //for(int i =0;i< bodySlicerGroup[(int)bodypart.Torso].Count; i++)
            //{
            TrickForSegment.BuildTorsoWithArmCutting(bodySlicerGroup[(int)bodypart.Torso], ref arm0top);
            TrickForSegment.BuildTorsoWithArmCutting(bodySlicerGroup[(int)bodypart.Torso], ref arm1top);
            bodySlicerGroup[(int)bodypart.Arm_0][0] = arm0top;
            bodySlicerGroup[(int)bodypart.Arm_1][0] = arm1top;
            //TrickForSegment.BuildTorsoSlicerCutByArm(torsoI, arm1top, out torsoI);
            //bodySlicerGroup[(int)bodypart.Torso][i] = torsoI;
            //}
            //TrickForSegment.BuildNewArmTopslicer(chestshoul, arm0top, out SlicerRecord nArm0);
            //TrickForSegment.BuildNewArmTopslicer(chestshoul, arm1top, out SlicerRecord nArm1);
            //GetMostMatchedArmSlicer(ref chestshoul,bodySlicerGroup[(int)bodypart.Arm_0][1],ref nArm0);
            //GetMostMatchedArmSlicer(ref chestshoul,bodySlicerGroup[(int)bodypart.Arm_1][1],ref nArm1);


            bodySlicerGroup[(int)bodypart.Head][0] = new SlicerRecord(bodySlicerGroup[(int)bodypart.Torso][0]); // 将躯干的slicer置换到头部
            bodySlicerGroup[(int)bodypart.Head][0].slicerNormal = -bodySlicerGroup[(int)bodypart.Head][0].slicerNormal;
            bodySlicerGroup[(int)bodypart.Leg_0][0]             = nLeg0;
            bodySlicerGroup[(int)bodypart.Leg_1][0]             = nLeg1;

            // add torso slicer in the bottom of torso
            TrickForSegment.BuildCombinedTorsoSlicer(leg0top, leg1top, out SlicerRecord torsoRoot);
            List <SlicerRecord> Torsoseq   = new List <SlicerRecord>();
            Vector3d            rootCentre = torsoRoot.slicerCenter;
            int    currLoopTimes           = (int)(Math.Floor((rootCentre - bottomTorso.slicerCenter).Length() / interval));
            double currInterval            = (rootCentre - bottomTorso.slicerCenter).Length() / currLoopTimes;

            for (int i = 1; i < currLoopTimes; i++)
            {
                Vector3d refSkeNode     = rootCentre + ((double)i / currLoopTimes) * (bottomTorso.slicerCenter - rootCentre);
                Vector3d refNodeNormal0 = ((double)i / currLoopTimes) * bottomTorso.slicerNormal +
                                          (1 - (double)i / currLoopTimes) * leg0top.slicerNormal;
                Vector3d refNodeNormal1 = ((double)i / currLoopTimes) * bottomTorso.slicerNormal +
                                          (1 - (double)i / currLoopTimes) * leg1top.slicerNormal;
                Plane        nodePlane0 = new Plane(refSkeNode, refNodeNormal0);
                Plane        nodePlane1 = new Plane(refSkeNode, refNodeNormal1);
                SlicerRecord t0         = new SlicerRecord(segMesh, nodePlane1);
                SlicerRecord t1         = new SlicerRecord(segMesh, nodePlane0);
                TrickForSegment.BuildCombinedTorsoSlicer(t0, t1, out SlicerRecord torsoIntp);
                Torsoseq.Add(torsoIntp);
            }
            Torsoseq.Reverse();
            Torsoseq.Add(torsoRoot);
            bodySlicerGroup[(int)bodypart.Torso].AddRange(Torsoseq);
        }
 public SlicerRecord(SlicerRecord ins1)
 {
     this.slicerNormal    = ins1.slicerNormal;
     this.slicerCenter    = ins1.slicerCenter;
     this.skeletonNodepos = ins1.skeletonNodepos;
     this.radius          = ins1.radius;
     this.perimeter       = ins1.perimeter;
     this.pointInfoList   = new List <PointRecord>(ins1.pointInfoList.ToArray());
     this.lineList        = new List <Lineindex>(ins1.lineList.ToArray());
 }
 public static void BuildSeperateLimbSlicer(SlicerRecord s1,
                                            SlicerRecord s2,
                                            out SlicerRecord outS1,
                                            out SlicerRecord outS2)
 {
     if (CreateTwoHalfSlicer(s1, s2, -(s1.slicerNormal + s2.slicerNormal).Normalize(),
                             out HalfSlicerRecord s1h, out HalfSlicerRecord s2h))
     {
         outS1 = new SlicerRecord(s1h);
         outS2 = new SlicerRecord(s2h);
     }
        private static void DisplaySlicer(SlicerRecord sli)
        {
            float skeletonNodeSize = 6.0f;

            float[] newcolor = ColorHelper.byte2float(Color.Gold);

            // draw center
            GL.glPointSize(skeletonNodeSize);
            GL.glColor3f(newcolor[0], newcolor[1], newcolor[2]);
            GL.glBegin(GL.GL_POINTS);
            GL.glVertex3d(sli.slicerCenter.x, sli.slicerCenter.y, sli.slicerCenter.z);
            GL.glEnd();
            newcolor = ColorHelper.byte2float(Color.Black);

            // mark skeleton node
            GL.glPointSize(skeletonNodeSize + 3);
            GL.glColor3f(newcolor[0], newcolor[1], newcolor[2]);
            GL.glBegin(GL.GL_POINTS);
            GL.glVertex3d(sli.skeletonNodepos.x, sli.skeletonNodepos.y, sli.skeletonNodepos.z);
            GL.glEnd();

            // draw points
            newcolor = ColorHelper.byte2float(Color.Orange);
            for (int i = 0; i < sli.pointInfoList.Count; i++)
            {
                GL.glPointSize(skeletonNodeSize);
                GL.glColor3f(newcolor[0], newcolor[1], newcolor[2]);
                GL.glBegin(GL.GL_POINTS);
                GL.glVertex3d(sli.pointInfoList[i].p.x, sli.pointInfoList[i].p.y, sli.pointInfoList[i].p.z);
                GL.glEnd();
            }

            // draw lines and mark mesh triangles
            newcolor = ColorHelper.byte2float(Color.Orange);
            float[] facemark = ColorHelper.byte2float(Color.Pink);
            for (int i = 0; i < sli.lineList.Count; i++)
            {
                GL.glColor3f(newcolor[0], newcolor[1], newcolor[2]);
                GL.glLineWidth(2.0f);
                GL.glBegin(GL.GL_LINES);
                int p1 = sli.lineList[i].p1;
                int p2 = sli.lineList[i].p2;
                GL.glVertex3d(sli.pointInfoList[p1].p.x, sli.pointInfoList[p1].p.y, sli.pointInfoList[p1].p.z);
                GL.glVertex3d(sli.pointInfoList[p2].p.x, sli.pointInfoList[p2].p.y, sli.pointInfoList[p2].p.z);
                GL.glEnd();
            }
        }
 public HalfSlicerRecord(SlicerRecord slicer, int i1, int i2)
 {
     this.slicerNormal = slicer.slicerNormal;
     if (i2 - i1 == slicer.pointInfoList.Count - 1)
     {
         this.pointInfoList = slicer.pointInfoList;
         this.lineList      = slicer.lineList;
     }
     else // normal
     {
         this.lineList      = slicer.lineList.GetRange(i1, i2 - i1 + 1); // 添加从i1开始的数据,一直添加到i2
         this.pointInfoList = slicer.pointInfoList.GetRange(i1, i2 - i1 + 1);
         if (i2 == slicer.pointInfoList.Count - 1) // 即最后一位的索引
         {
             // add slicer fid and p
             this.pointInfoList.Add(new PointRecord(slicer.pointInfoList[0].p, slicer.lineList[0].fid));
         }
         else
         {
             this.pointInfoList.Add(new PointRecord(slicer.pointInfoList[i2].p, slicer.lineList[i2].fid));
         }
     }
 }
Beispiel #8
0
        /// <summary>
        /// 这个函数是用来对手臂上的分片进行特殊处理的,是CreateSlicerSequence的分支,后面还需要对躯干与手臂进行交叉
        /// </summary>
        /// <param name="bdt"></param>
        /// <param name="interval"></param>
        /// <param name="slicerSeq"></param>
        private void CreateArmSlicerSequence(bodypart bdt, double interval, List <SlicerRecord> slicerSeq)
        {
            List <int> skeletonSeq  = partSkelSeq[(int)bdt];
            int        foreArmIndex = skeletonSeq.Count / 8 - 1;
            Vector3d   torso2ArmDir = skeRcd.nodePosList[skeletonSeq[foreArmIndex]] - skeRcd.nodePosList[skeletonSeq[0]];                         // 得到初始的法向量

            Vector3d armEndDir = skeRcd.nodePosList[skeletonSeq[skeletonSeq.Count - 1]] - skeRcd.nodePosList[skeletonSeq[skeletonSeq.Count - 2]]; // 得到末端的法向量

            #region get the length of skeleton and compute two intervals of relative slicer sknode.
            double pSkeLen = 0.0;
            for (int i = 0; i < skeletonSeq.Count - 1; i++)
            {
                pSkeLen += (skeRcd.nodePosList[skeletonSeq[i + 1]] - skeRcd.nodePosList[skeletonSeq[i]]).Length();
            }
            interval = pSkeLen / (Math.Floor(pSkeLen / interval)) + interval / 200;
            double oxterInterval = interval / 5;  // 寻找腋窝的interval 细化
            #endregion
            //Vector3d nodeNV;
            Vector3d nodepos;
            Plane    nodePlane;
            List <KeyValuePair <int, int> > skeEndIndex = new List <KeyValuePair <int, int> >();
            // 因为起点的slicer并不需要所以直接舍弃
            double globalPos    = oxterInterval; // 整个骨架序列线段中的位置
            double skeLineAddup = 0.0;           // 单个骨架线中的位置
            int    skeLineIndex = 0;             // 骨架序列索引
            do
            {
                int    currStartIndex = 0;
                int    currEndIndex   = 1;
                double currLineLen    = (skeRcd.nodePosList[1] - skeRcd.nodePosList[0]).Length();
                for (; skeLineAddup < globalPos; skeLineIndex++)
                {
                    currStartIndex = skeletonSeq[skeLineIndex];
                    currEndIndex   = skeletonSeq[skeLineIndex + 1];
                    currLineLen    = (skeRcd.nodePosList[currEndIndex] - skeRcd.nodePosList[currStartIndex]).Length();
                    skeLineAddup  += currLineLen;
                }// 循环停止的结果:skeLineAddup>=globalPos skeLineIndex指向超过globalpos的那个线段
                if (skeEndIndex.Count == 0 || currEndIndex != skeEndIndex.Last().Key)
                {
                    skeEndIndex.Add(new KeyValuePair <int, int>(currEndIndex, skeLineIndex - 1));
                    nodepos = (1 - (skeLineAddup - globalPos) / currLineLen) *
                              (skeRcd.nodePosList[currEndIndex] - skeRcd.nodePosList[currStartIndex]) +
                              skeRcd.nodePosList[currStartIndex];
                    //nodeNV = skeRcd.nodePosList[currEndIndex] - skeRcd.nodePosList[currStartIndex]; 这里注释了
                    nodePlane = new Plane(nodepos, torso2ArmDir);
                    slicerSeq.Add(new SlicerRecord(segMesh, nodePlane));
                }
                globalPos += oxterInterval;
            } while (globalPos < pSkeLen);
            // find oxter slicer
            Diff2rdPrune(slicerSeq, out int outstart);  // outstart 就是腋窝的index

            // 进行手臂的分片生成
            SlicerRecord temp = slicerSeq[outstart];
            slicerSeq.Clear();
            slicerSeq.Add(temp);
            double armLength = 0.0;
            for (int i = skeEndIndex[outstart].Value; i < skeletonSeq.Count - 1; i++)
            {
                armLength += (skeRcd.nodePosList[skeletonSeq[i + 1]] - skeRcd.nodePosList[skeletonSeq[i]]).Length();
            }
            double foreArmLength = armLength / 3 * 2;
            interval = armLength / (Math.Floor(armLength / interval)) + interval / 200;
            Vector3d nodeNV;
            globalPos    = interval;                    // 整个骨架序列线段中的位置
            skeLineAddup = 0.0;                         // 单个骨架线中的位置
            skeLineIndex = skeEndIndex[outstart].Value; // 骨架序列索引
            do
            {
                int    currStartIndex = skeletonSeq[skeLineIndex];
                int    currEndIndex   = skeletonSeq[skeLineIndex + 1];
                double currLineLen    = (skeRcd.nodePosList[currEndIndex] - skeRcd.nodePosList[currStartIndex]).Length();
                for (; skeLineAddup < globalPos; skeLineIndex++)
                {
                    currStartIndex = skeletonSeq[skeLineIndex];
                    currEndIndex   = skeletonSeq[skeLineIndex + 1];
                    currLineLen    = (skeRcd.nodePosList[currEndIndex] - skeRcd.nodePosList[currStartIndex]).Length();
                    skeLineAddup  += currLineLen;
                }// 循环停止的结果:skeLineAddup>=globalPos skeLineIndex指向超过globalpos的那个线段
                nodepos = (1 - (skeLineAddup - globalPos) / currLineLen) *
                          (skeRcd.nodePosList[currEndIndex] - skeRcd.nodePosList[currStartIndex]) +
                          skeRcd.nodePosList[currStartIndex];
                if (skeLineAddup < foreArmLength)
                {
                    nodeNV = (skeLineAddup * (skeRcd.nodePosList[currEndIndex] - skeRcd.nodePosList[currStartIndex]) +
                              (foreArmLength - skeLineAddup) * torso2ArmDir) / (foreArmLength); //这里注释了
                }
                else
                {
                    nodeNV = (skeRcd.nodePosList[currEndIndex] - skeRcd.nodePosList[currStartIndex]).Normalize();
                }

                nodePlane = new Plane(nodepos, nodeNV);
                slicerSeq.Add(new SlicerRecord(segMesh, nodePlane));
                globalPos += interval * (1 / nodeNV.Normalize().Dot((skeRcd.nodePosList[currEndIndex] - skeRcd.nodePosList[currStartIndex]).Normalize()));
            } while (globalPos < armLength);
            // final cut slicer
            nodeNV    = skeRcd.nodePosList[skeletonSeq[skeletonSeq.Count - 1]] - skeRcd.nodePosList[skeletonSeq[skeletonSeq.Count - 2]];
            nodePlane = new Plane(skeRcd.nodePosList[skeletonSeq.Last()], nodeNV);
            slicerSeq.Add(new SlicerRecord(segMesh, nodePlane));
        }
Beispiel #9
0
        private void DisplaySlicer(SlicerRecord sli)
        {
            float skeletonNodeSize = 6.0f;

            float[] newcolor = ColorHelper.byte2float(Color.Gold);

            // draw center
            GL.glPointSize(skeletonNodeSize);
            GL.glColor3f(newcolor[0], newcolor[1], newcolor[2]);
            GL.glBegin(GL.GL_POINTS);
            GL.glVertex3d(sli.slicerCenter.x, sli.slicerCenter.y, sli.slicerCenter.z);
            GL.glEnd();
            newcolor = ColorHelper.byte2float(Color.Black);

            // mark skeleton node
            GL.glPointSize(skeletonNodeSize + 3);
            GL.glColor3f(newcolor[0], newcolor[1], newcolor[2]);
            GL.glBegin(GL.GL_POINTS);
            GL.glVertex3d(sli.skeletonNodepos.x, sli.skeletonNodepos.y, sli.skeletonNodepos.z);
            GL.glEnd();

            // draw points
            newcolor = ColorHelper.byte2float(Color.Orange);
            for (int i = 0; i < sli.pointInfoList.Count; i++)
            {
                GL.glPointSize(skeletonNodeSize);
                GL.glColor3f(newcolor[0], newcolor[1], newcolor[2]);
                GL.glBegin(GL.GL_POINTS);
                GL.glVertex3d(sli.pointInfoList[i].p.x, sli.pointInfoList[i].p.y, sli.pointInfoList[i].p.z);
                GL.glEnd();
            }

            // draw lines and mark mesh triangles
            newcolor = ColorHelper.byte2float(Color.Orange);
            float[] facemark = ColorHelper.byte2float(Color.Pink);
            for (int i = 0; i < sli.lineList.Count; i++)
            {
                GL.glColor3f(newcolor[0], newcolor[1], newcolor[2]);
                GL.glLineWidth(2.0f);
                GL.glBegin(GL.GL_LINES);
                int p1 = sli.lineList[i].p1;
                int p2 = sli.lineList[i].p2;
                GL.glVertex3d(sli.pointInfoList[p1].p.x, sli.pointInfoList[p1].p.y, sli.pointInfoList[p1].p.z);
                GL.glVertex3d(sli.pointInfoList[p2].p.x, sli.pointInfoList[p2].p.y, sli.pointInfoList[p2].p.z);
                GL.glEnd();
            }
            //unsafe
            //{
            //    fixed (double* np = segMesh.FaceNormal)
            //    fixed (double* vp = segMesh.VertexPos)
            //    {
            //        for (int i = 0; i < sli.lineList.Count; i++)
            //        {
            //            int fi = sli.lineList[i].fid;
            //            GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL);
            //            GL.glColor3f(facemark[0], facemark[1], facemark[2]);
            //            GL.glEnableClientState(GL.GL_VERTEX_ARRAY);
            //            GL.glNormal3dv(np + fi);
            //            GL.glVertex3dv(vp + segMesh.FaceIndex[fi] * 3);
            //            GL.glVertex3dv(vp + segMesh.FaceIndex[fi + 1] * 3);
            //            GL.glVertex3dv(vp + segMesh.FaceIndex[fi + 2] * 3);
            //            GL.glEnd();
            //        }
            //    }
            //}
        }