Example #1
0
        /// <summary>
        /// get interatomic contacts
        /// </summary>
        /// <param name="treeA"></param>
        /// <param name="treeB"></param>
        /// <returns></returns>
        public ChainContactInfo GetAnyChainContactInfo(BVTree treeA, BVTree treeB)
        {
            chainContactInfo = new ChainContactInfo();
            if (BVTree.treeType == '1')
            {
                IntersectResidues(treeA, treeB);

                /*    if (chainContactInfo.atomContactHash.Count == 0 || chainContactInfo.cbetaContactHash.Count == 0)
                 *  {
                 *      chainContactInfo = null;
                 *      return null;
                 *  }*/
            }
            else
            {
                Intersect(treeA, treeB);

                /*    if (chainContactInfo.atomContactHash.Count == 0)
                 *  {
                 *      chainContactInfo = null;
                 *      return null;
                 *  }*/
            }
            return(chainContactInfo);
        }
Example #2
0
 /// <summary>
 /// return the overlapped leaf nodes
 /// </summary>
 /// <param name="extTree"></param>
 /// <returns></returns>
 public void Intersect(BVTree treeA, BVTree treeB)
 {
     if (treeA == null || treeB == null)
     {
         return;
     }
     if (!treeA.Root.BoundBox.MayOverlap
             (treeB.Root.BoundBox, AppSettings.parameters.contactParams.cutoffAtomDist))
     {
         return;
     }
     // if it is a leaf node of tree A
     if (treeA.Root.AtomList.Length <= BVTree.leafAtomNumber)
     {
         // it is a leaf node of tree B
         if (treeB.Root.AtomList.Length <= BVTree.leafAtomNumber)
         {
             foreach (AtomInfo atomA in treeA.Root.AtomList)
             {
                 foreach (AtomInfo atomB in treeB.Root.AtomList)
                 {
                     float atomDist = (float)(atomA - atomB);
                     // if distance is less than the threshold
                     // possible atomic contact
                     if (atomDist < AppSettings.parameters.contactParams.cutoffAtomDist)
                     {
                         AtomPair atomPair = new AtomPair();
                         atomPair.firstAtom  = atomA;
                         atomPair.secondAtom = atomB;
                         atomPair.distance   = atomDist;
                         string seqIdString = atomA.seqId + "_" + atomB.seqId;
                         if (!chainContactInfo.atomContactHash.ContainsKey(seqIdString))
                         {
                             chainContactInfo.atomContactHash.Add(seqIdString, atomPair);
                         }
                         else
                         {
                             // give priority to Cbeta then Calpha
                             if (atomPair.firstAtom.atomName == "CB" && atomPair.secondAtom.atomName == "CB")
                             {
                                 chainContactInfo.atomContactHash[seqIdString] = atomPair;
                             }
                         }
                     }
                 }
             }
         }
         else
         {
             Intersect(treeA, treeB.LeftBranch);
             Intersect(treeA, treeB.RightBranch);
         }
     }
     else
     {
         Intersect(treeA.LeftBranch, treeB);
         Intersect(treeA.RightBranch, treeB);
     }
 }
Example #3
0
 /// <summary>
 /// interactive chains from all pairs of 2 asymmetric chains +
 /// their corresponding translated chains
 /// </summary>
 /// <param name="chainASymOp"></param>
 /// <param name="chainBSymOp"></param>
 /// <param name="origTreeA">chain A in the center unit cell
 /// can be a transformed chain from one chain in the asymmetry unit
 /// after applied symmetry operation </param>
 /// <param name="origTreeB">chain B in the center unit cell(description same as chain A)</param>
 private bool  DetectChainContactWithTranslation(string chainASymOp, string chainBSymOp,
                                                 BVTree origTreeA, BVTree origTreeB, bool skipOrig)
 {
     // compare center chain A with all translated chain B
     // translated BVTrees for chain B
     return(DetectTwoChainContactWithTranslation
                (chainBSymOp, chainASymOp, origTreeB, origTreeA, skipOrig));
 }
Example #4
0
        /// <summary>
        /// Detect all interfaces in a crystal
        /// built from XML coordinates file
        /// </summary>
        /// <param name="xmlFile"></param>
        /// <param name="paramFile"></param>
        public void FindInteractChains(string xmlFile, Dictionary <int, string> interfaceDefHash)
        {
            asymChainTreesHash.Clear();
            interfaceChainsList.Clear();
            string[] symOpStrings = GetSymOpStrings(interfaceDefHash);
            if (AppSettings.parameters == null)
            {
                AppSettings.LoadParameters();
            }

            pdbId = xmlFile.Substring(xmlFile.LastIndexOf("\\") + 1, 4);
            CrystalBuilder crystalBuilder = new CrystalBuilder("ALL");
            Dictionary <string, AtomInfo[]> interfaceChainHash = null;

            try
            {
                interfaceChainHash = crystalBuilder.BuildCrystal(xmlFile, symOpStrings);
            }
            catch (Exception ex)
            {
                throw new Exception("Building interface chains errors: " + xmlFile + ". " + ex.Message);
            }

            // for each chain in a cell including original and symmetric chains
            foreach (string chainAndSymOp in interfaceChainHash.Keys)
            {
                BVTree chainTree = new BVTree();
                chainTree.BuildBVTree(interfaceChainHash[chainAndSymOp], AppSettings.parameters.kDopsParam.bvTreeMethod, true);
                asymChainTreesHash.Add(chainAndSymOp, chainTree);
            }

            ChainContact chainContact  = null;
            List <int>   interfaceList = new List <int> (interfaceDefHash.Keys);

            interfaceList.Sort();
            foreach (int interfaceId in interfaceList)
            {
                string[] interfaceDefStrings = interfaceDefHash[interfaceId].ToString().Split(';');
                chainContact = new ChainContact(interfaceDefStrings[0], interfaceDefStrings[1]);
                BVTree           tree1       = (BVTree)asymChainTreesHash[interfaceDefStrings[0]];
                BVTree           tree2       = (BVTree)asymChainTreesHash[interfaceDefStrings[1]];
                ChainContactInfo contactInfo = chainContact.GetChainContactInfo(tree1, tree2);

                if (contactInfo == null)
                {
                    continue;
                }
                InterfaceChains interfaceChains = null;
                interfaceChains = new InterfaceChains(interfaceDefStrings[0], interfaceDefStrings[1],
                                                      tree1.Root.AtomList, tree2.Root.AtomList);
                interfaceChains.pdbId       = pdbId;
                interfaceChains.interfaceId = interfaceId;
                interfaceChains.seqDistHash = contactInfo.GetBbDistHash();
                //      interfaceChains.seqDistHash = contactInfo.cbetaContactHash;
                interfaceChains.seqContactHash = contactInfo.GetContactsHash();
                interfaceChainsList.Add(interfaceChains);
            }
        }
Example #5
0
        /// <summary>
        /// get the interface between two input chains
        /// </summary>
        /// <param name="chain1"></param>
        /// <param name="chain2"></param>
        /// <returns></returns>
        public ChainContactInfo GetAllChainContactInfo(AtomInfo[] chain1, AtomInfo[] chain2)
        {
            BVTree chain1Tree = new BVTree();

            chain1Tree.BuildBVTree(chain1, AppSettings.parameters.kDopsParam.bvTreeMethod, true);
            BVTree chain2Tree = new BVTree();

            chain2Tree.BuildBVTree(chain2, AppSettings.parameters.kDopsParam.bvTreeMethod, true);
            return(GetAnyChainContactInfo(chain1Tree, chain2Tree));
        }
Example #6
0
 /// <summary>
 /// get interatomic contacts
 /// </summary>
 /// <param name="treeA"></param>
 /// <param name="treeB"></param>
 /// <returns></returns>
 public ChainContactInfo GetDomainContactInfo(BVTree treeA, BVTree treeB)
 {
     chainContactInfo = new ChainContactInfo();
     Intersect(treeA, treeB);
     if (chainContactInfo.atomContactHash.Count < AppSettings.parameters.contactParams.domainNumOfAtomContacts)
     {
         chainContactInfo = null;
         return(null);
     }
     return(chainContactInfo);
 }
Example #7
0
        /// <summary>
        /// build BVtrees for chains in a biological unit
        /// </summary>
        /// <param name="biolUnit"></param>
        /// <returns></returns>
        private Dictionary <string, BVTree> BuildBVtreesForAsu(Dictionary <string, AtomInfo[]> asymUnit)
        {
            Dictionary <string, BVTree> chainTreesHash = new Dictionary <string, BVTree> ();

            // for each chain in the biological unit
            // build BVtree
            foreach (string chainAndSymOp in asymUnit.Keys)
            {
                BVTree chainTree = new BVTree();
                chainTree.BuildBVTree(asymUnit[chainAndSymOp], AppSettings.parameters.kDopsParam.bvTreeMethod, true);
                chainTreesHash.Add(chainAndSymOp, chainTree);
            }
            return(chainTreesHash);
        }
Example #8
0
 /// <summary>
 /// read only
 /// if two input chains overlap or not
 /// </summary>
 public bool IsChainInteract(BVTree treeA, BVTree treeB)
 {
     chainContactInfo = new ChainContactInfo();
     if (BVTree.treeType == '1')
     {
         IntersectResidues(treeA, treeB);
         if (chainContactInfo.atomContactHash.Count < AppSettings.parameters.contactParams.numOfAtomContacts ||
             chainContactInfo.cbetaContactHash.Count < AppSettings.parameters.contactParams.numOfResidueContacts)
         {
             chainContactInfo = null;
             return(false);
         }
     }
     else
     {
         Intersect(treeA, treeB);
         if (chainContactInfo.atomContactHash.Count < AppSettings.parameters.contactParams.numOfResidueContacts)
         {
             chainContactInfo = null;
             return(false);
         }
     }
     return(true);
 }
Example #9
0
 /// <summary>
 /// get interatomic contacts
 /// </summary>
 /// <param name="treeA"></param>
 /// <param name="treeB"></param>
 /// <returns></returns>
 public ChainContactInfo GetChainContactInfo(BVTree treeA, BVTree treeB, double [] translateVectorA)
 {
     chainContactInfo = new ChainContactInfo();
     if (BVTree.treeType == '1')
     {
         IntersectResidues(treeA, treeB, translateVectorA);
         if (chainContactInfo.atomContactHash.Count < AppSettings.parameters.contactParams.numOfAtomContacts ||
             chainContactInfo.cbetaContactHash.Count < AppSettings.parameters.contactParams.numOfResidueContacts)
         {
             chainContactInfo = null;
             return(null);
         }
     }
     else
     {
         Intersect(treeA, treeB, translateVectorA);
         if (chainContactInfo.atomContactHash.Count < AppSettings.parameters.contactParams.numOfResidueContacts)
         {
             chainContactInfo = null;
             return(null);
         }
     }
     return(chainContactInfo);
 }
Example #10
0
        /// <summary>
        /// Detect all interfaces in a crystal
        /// built from XML coordinates file
        /// </summary>
        /// <param name="xmlFile"></param>
        /// <param name="paramFile"></param>
        public int FindInteractChains(string xmlFile)
        {
            interChainId = 0;
            asymChainTreesHash.Clear();
            interfaceChainsList.Clear();
            pdbId = xmlFile.Substring(xmlFile.LastIndexOf("\\") + 1, 4);
            CrystalBuilder crystalBuilder = new CrystalBuilder(AppSettings.parameters.contactParams.atomType);
            Dictionary <string, AtomInfo[]> unitCellChainsHash = null;

            int[] maxSteps = null;
            // build crystal based on all symmetry operations
            try
            {
                maxSteps = crystalBuilder.BuildCrystal(xmlFile, ref unitCellChainsHash);
                if (unitCellChainsHash == null)
                {
                    throw new Exception("Cannot build unit cell.");
                }
                // if there are too many chains in a unit cell
                // only compute the interfaces between original ASU chains
                // and other chains
                if (unitCellChainsHash.Count > unitCellSize)
                {
                    //	throw new Exception ("Unit cell too large. Skip processing " + pdbId + ".");
                    // if there are too many chains in the unit cell,
                    // only check the interfaces within the unit cell.
                    for (int i = 0; i < maxSteps.Length; i++)
                    {
                        maxSteps[i] = 0;
                    }
                }
                // if there are too many chains, only use chains in the asymmetric unit
                if (unitCellChainsHash.Count >= maxUnitCellSize)
                {
                    Dictionary <string, AtomInfo[]> asuChainHash = GetAsymUnitHash(unitCellChainsHash);
                    unitCellChainsHash = asuChainHash;
                    // if it is still too big due to Non-symmetry operators,
                    // only use chains in the original asu in the PDB file, may not be the real Asu
                    if (asuChainHash.Count >= unitCellSize)
                    {
                        Dictionary <string, AtomInfo[]> origAsuChainHash = GetOrigAsymUnitHash(asuChainHash);
                        unitCellChainsHash = origAsuChainHash;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Building Crystal Errors: " + xmlFile + " " + ex.Message);
            }

            /*
             * build BVTree for original asymmetric chains +
             * their chains after applied symmetry operations
             * without translations
             */
            try
            {
                // for each chain in a cell including original and symmetric chains
                foreach (string chainAndSymOp in unitCellChainsHash.Keys)
                {
                    BVTree chainTree = new BVTree();
                    chainTree.BuildBVTree(unitCellChainsHash[chainAndSymOp], AppSettings.parameters.kDopsParam.bvTreeMethod, true);
                    asymChainTreesHash.Add(chainAndSymOp, chainTree);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Building Bounding Volumn Tree Errors: " + xmlFile + ". " + ex.Message);
            }

            /*
             * the critical step for the computation time
             * check all pairs of chains including translated chains
             * return a list of atompairs if exists
             */
            cryst1            = crystalBuilder.Crystal1;
            fract2CartnMatrix = crystalBuilder.fract2cartnMatrix;

            List <string> chainAndSymOps        = new List <string> (asymChainTreesHash.Keys);
            List <string> orderedChainAndSymOps = SortChainsInUnitCell(chainAndSymOps);

            // check interactions between 2 different chains and their translated chains
            // chainAndSymOps: chainId_symmetry operator_full symmetry operations
            // e.g. A_1_545
            try
            {
                ComputeUniqueInterfacesFromCryst(orderedChainAndSymOps, maxSteps);
            }
            catch (Exception ex)
            {
                /*	ProtCidSettings.progressInfo.progStrQueue.Enqueue
                 *              ("Retrieving unique interfaces of " + pdbId + " errors: " + ex.Message);*/
                throw new Exception("Retrieving unique interfaces of " + pdbId + " errors: " + ex.Message);
            }
            return(unitCellChainsHash.Count);
        }
Example #11
0
        /// <summary>
        /// Detect all interfaces in a crystal
        /// built from XML coordinates file
        /// </summary>
        /// <param name="xmlFile"></param>
        /// <param name="paramFile"></param>
        public void FindInteractChains(string xmlFile, Dictionary <int, string> interfaceDefHash, Dictionary <int, string> interfaceEntityInfoHash, out bool interfaceExist)
        {
            interChainId = 0;
            interfaceChainsList.Clear();
            asymChainTreesHash.Clear();
            interfaceExist = true;
            string[] symOpStrings = GetSymOpStrings(interfaceDefHash);

            pdbId = xmlFile.Substring(xmlFile.LastIndexOf("\\") + 1, 4);
            CrystalBuilder crystalBuilder = new CrystalBuilder(AppSettings.parameters.contactParams.atomType);
            Dictionary <string, AtomInfo[]> interfaceChainHash = null;

            try
            {
                interfaceChainHash = crystalBuilder.BuildCrystal(xmlFile, symOpStrings);
            }
            catch (Exception ex)
            {
                throw new Exception("Building interface chains errors: " + xmlFile + "  " + ex.Message);
            }

            // for each chain in a cell including original and symmetric chains
            foreach (string chainAndSymOp in interfaceChainHash.Keys)
            {
                BVTree chainTree = new BVTree();
                chainTree.BuildBVTree(interfaceChainHash[chainAndSymOp], AppSettings.parameters.kDopsParam.bvTreeMethod, true);
                asymChainTreesHash.Add(chainAndSymOp, chainTree);
            }

            ChainContact chainContact = null;

            foreach (int interfaceId in interfaceDefHash.Keys)
            {
                string[] interfaceDefStrings = interfaceDefHash[interfaceId].ToString().Split(';');
                chainContact = new ChainContact(interfaceDefStrings[0], interfaceDefStrings[1]);
                BVTree tree1 = (BVTree)asymChainTreesHash[interfaceDefStrings[0]];
                BVTree tree2 = (BVTree)asymChainTreesHash[interfaceDefStrings[1]];
                if (tree1 == null || tree2 == null)
                {
                    continue;
                }
                ChainContactInfo contactInfo = chainContact.GetChainContactInfo(tree1, tree2);

                if (contactInfo == null)
                {
                    interfaceExist = false;
                    break;
                }
                string[]        entityStrings   = interfaceEntityInfoHash[interfaceId].Split('_');
                InterfaceChains interfaceChains = null;
                interfaceChains = new InterfaceChains(interfaceDefStrings[0], interfaceDefStrings[1], tree1.Root.CalphaCbetaAtoms(), tree2.Root.CalphaCbetaAtoms());
                //	interfaceChains = new InterfaceChains (symOpStrings[0], symOpStrings[1], tree1.Root.AtomList, tree2.Root.AtomList);
                interfaceChains.pdbId          = pdbId;
                interfaceChains.interfaceId    = interfaceId;
                interfaceChains.entityId1      = Convert.ToInt32(entityStrings[0]);
                interfaceChains.entityId2      = Convert.ToInt32(entityStrings[1]);
                interfaceChains.seqDistHash    = contactInfo.GetBbDistHash();
                interfaceChains.seqContactHash = contactInfo.GetContactsHash();
                interfaceChainsList.Add(interfaceChains);
            }
        }
Example #12
0
        /// <summary>
        /// check interaction a center chain with
        /// another translated chains
        /// </summary>
        /// <param name="chainASymOp">translated chain</param>
        /// <param name="chainBSymOp">center chain</param>
        /// <param name="treeA">translated tree</param>
        /// <param name="treeB">center tree</param>
        private bool DetectTwoChainContactWithTranslation(string translateChainSymOp, string centerChainSymOp,
                                                          BVTree translateTree, BVTree centerTree, bool skipOrig)
        {
            string transChainSymOp = "";
            int    origX           = -1;
            int    origY           = -1;
            int    origZ           = -1;
            string transVectString = translateChainSymOp.Substring(translateChainSymOp.LastIndexOf("_") + 1,
                                                                   translateChainSymOp.Length - translateChainSymOp.LastIndexOf("_") - 1);

            GetOrigPoint(transVectString, ref origX, ref origY, ref origZ);

            bool thisNewInterfaceExist = false;


            try
            {
                ChainContact chainContact = null;

                /* total number of BVTrees: (step * 2 + 1) ^ 3
                 * total comparison of BVTrees: (step * 2 + 1) - 1
                 * e.g. steps = 1; total comparisons: 26
                 * compare all neighbor unit cells with the original unit cell
                 */
                // comare center chain B with center chain A and all its translated chains
                foreach (int xA in xStepList)
                {
                    foreach (int yA in yStepList)
                    {
                        foreach (int zA in zStepList)
                        {
                            if (xA == 0 && yA == 0 && zA == 0 && skipOrig)
                            {
                                thisNewInterfaceExist = true;
                                continue;
                            }
                            // chain_symmetry operator number_translation vector
                            // e.g. A_1_556 (chain A, symmetry operator is 1, and translation vector (0, 0, 1))
                            transChainSymOp = GetTransSymOpString(translateChainSymOp, origX + xA, origY + yA, origZ + zA);
                            if (parsedPairList.Contains(centerChainSymOp + "_" + transChainSymOp))
                            {
                                continue;
                            }
                            else
                            {
                                parsedPairList.Add(centerChainSymOp + "_" + transChainSymOp);
                            }

                            double[] fractVectorA = new double [3] {
                                xA, yA, zA
                            };
                            double[] translateVectorA = ComputeTransVectInCartn(fractVectorA);
                            //	BVTree translatedTree = translateTree.UpdateBVTree (translateVectorA);

                            chainContact = new ChainContact(centerChainSymOp, transChainSymOp);
                            ChainContactInfo contactInfo = chainContact.GetChainContactInfo(centerTree, translateTree, translateVectorA);
                            if (contactInfo != null)
                            {
                                InterfaceChains interfaceChains = null;
                                Node            updateRoot      = new Node(translateTree.Root.CalphaCbetaAtoms());
                                updateRoot.UpdateLeafNode(translateVectorA);
                                interfaceChains = new InterfaceChains(centerChainSymOp, transChainSymOp,
                                                                      centerTree.Root.CalphaCbetaAtoms(), updateRoot.AtomList);
                                interfaceChains.seqDistHash    = contactInfo.GetBbDistHash();
                                interfaceChains.seqContactHash = contactInfo.GetContactsHash();
                                if (AddInterChainsToList(interfaceChains))
                                {
                                    thisNewInterfaceExist = true;
                                }
                            }
                        }
                    }
                }                // end of translated chain
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("Comparisons of rotated and translated chains ({0}, {1}) errors: {2}",
                                                  translateChainSymOp, centerChainSymOp, ex.Message));
            }
            return(thisNewInterfaceExist);
        }
Example #13
0
        /// <summary>
        /// check interaction a center chain with
        /// its corresponding translated chains
        /// </summary>
        /// <param name="chainASymOp"></param>
        /// <param name="chainBSymOp"></param>
        /// <param name="treeA"></param>
        /// <param name="treeB"></param>
        private bool DetectChainContactWithTranslation(string chainASymOp, BVTree origTreeA)
        {
            string        transChainASymOp = "";
            List <string> parsedSymOpsList = new List <string> ();
            int           origX            = -1;
            int           origY            = -1;
            int           origZ            = -1;
            string        transVectString  = chainASymOp.Substring(chainASymOp.LastIndexOf("_") + 1,
                                                                   chainASymOp.Length - chainASymOp.LastIndexOf("_") - 1);

            GetOrigPoint(transVectString, ref origX, ref origY, ref origZ);

            bool thisNewInterfaceExist = false;

            /* total number of BVTrees: (step * 2 + 1) ^ 3
             * total comparison of BVTrees: (step * 2 + 1) - 1
             * e.g. steps = 1; total comparisons: 26
             * compare all neighbor unit cells with the original unit cell
             */
            // compare a center chain with all its corresponding translated chains
            foreach (int xA in xStepList)
            {
                foreach (int yA in yStepList)
                {
                    foreach (int zA in zStepList)
                    {
                        // skip check contacts with itself
                        // probably we need to check contacts within a chain also.
                        if (xA == 0 && yA == 0 && zA == 0)
                        {
                            thisNewInterfaceExist = true;
                            continue;
                        }

                        transChainASymOp = GetTransSymOpString(chainASymOp, origX + xA, origY + yA, origZ + zA);
                        if (parsedPairList.Contains(chainASymOp + "_" + transChainASymOp))
                        {
                            continue;
                        }
                        else
                        {
                            parsedPairList.Add(chainASymOp + "_" + transChainASymOp);
                        }

                        double[] fractVectorA = new double [3] {
                            xA, yA, zA
                        };
                        double[] translateVectorA = ComputeTransVectInCartn(fractVectorA);

                        // get the BVtree for the translated chain
                        //	BVTree treeA = origTreeA.UpdateBVTree (translateVectorA);

                        ChainContact     chainContact = new ChainContact(chainASymOp, transChainASymOp);
                        ChainContactInfo contactInfo  = chainContact.GetChainContactInfo(origTreeA, origTreeA, translateVectorA);
                        if (contactInfo != null)
                        {
                            InterfaceChains interfaceChains = null;
                            Node            updateRoot      = new Node(origTreeA.Root.CalphaCbetaAtoms());
                            updateRoot.UpdateLeafNode(translateVectorA);
                            interfaceChains = new InterfaceChains(chainASymOp, transChainASymOp,
                                                                  origTreeA.Root.CalphaCbetaAtoms(), updateRoot.AtomList);
                            interfaceChains.seqDistHash    = contactInfo.GetBbDistHash();
                            interfaceChains.seqContactHash = contactInfo.GetContactsHash();
                            if (AddInterChainsToList(interfaceChains))
                            {
                                thisNewInterfaceExist = true;
                            }
                        }
                    }
                }
            }
            return(thisNewInterfaceExist);
        }
Example #14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="NavMeshBuilder" /> class.
        /// Add all the PolyMesh and PolyMeshDetail attributes to the Navigation Mesh.
        /// Then, add Off-Mesh connection support.
        /// </summary>
        /// <param name="polyMesh">The PolyMesh</param>
        /// <param name="polyMeshDetail">The PolyMeshDetail</param>
        /// <param name="offMeshCons">Offmesh connection data</param>
        /// <param name="settings">The settings used to build.</param>
        public NavMeshBuilder(PolyMesh polyMesh, PolyMeshDetail polyMeshDetail, OffMeshConnection[] offMeshCons, NavMeshGenerationSettings settings)
        {
            if (settings.VertsPerPoly > PathfindingCommon.VERTS_PER_POLYGON)
            {
                throw new InvalidOperationException("The number of vertices per polygon is above SharpNav's limit");
            }
            if (polyMesh.VertCount == 0)
            {
                throw new InvalidOperationException("The provided PolyMesh has no vertices.");
            }
            if (polyMesh.PolyCount == 0)
            {
                throw new InvalidOperationException("The provided PolyMesh has not polys.");
            }

            int nvp = settings.VertsPerPoly;

            //classify off-mesh connection points
            BoundarySide[] offMeshSides          = new BoundarySide[offMeshCons.Length * 2];
            int            storedOffMeshConCount = 0;
            int            offMeshConLinkCount   = 0;

            if (offMeshCons.Length > 0)
            {
                //find height bounds
                float hmin = float.MaxValue;
                float hmax = -float.MaxValue;

                if (polyMeshDetail != null)
                {
                    for (int i = 0; i < polyMeshDetail.VertCount; i++)
                    {
                        float h = polyMeshDetail.Verts[i].Y;
                        hmin = Math.Min(hmin, h);
                        hmax = Math.Max(hmax, h);
                    }
                }
                else
                {
                    for (int i = 0; i < polyMesh.VertCount; i++)
                    {
                        PolyVertex iv = polyMesh.Verts[i];
                        float      h  = polyMesh.Bounds.Min.Y + iv.Y * settings.CellHeight;
                        hmin = Math.Min(hmin, h);
                        hmax = Math.Max(hmax, h);
                    }
                }

                hmin -= settings.MaxClimb;
                hmax += settings.MaxClimb;
                BBox3 bounds = polyMesh.Bounds;
                bounds.Min.Y = hmin;
                bounds.Max.Y = hmax;

                for (int i = 0; i < offMeshCons.Length; i++)
                {
                    Vector3 p0 = offMeshCons[i].Pos0;
                    Vector3 p1 = offMeshCons[i].Pos1;

                    offMeshSides[i * 2 + 0] = BoundarySideExtensions.FromPoint(p0, bounds);
                    offMeshSides[i * 2 + 1] = BoundarySideExtensions.FromPoint(p1, bounds);

                    //off-mesh start position isn't touching mesh
                    if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
                    {
                        if (p0.Y < bounds.Min.Y || p0.Y > bounds.Max.Y)
                        {
                            offMeshSides[i * 2 + 0] = 0;
                        }
                    }

                    //count number of links to allocate
                    if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
                    {
                        offMeshConLinkCount++;
                    }
                    if (offMeshSides[i * 2 + 1] == BoundarySide.Internal)
                    {
                        offMeshConLinkCount++;
                    }

                    if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
                    {
                        storedOffMeshConCount++;
                    }
                }
            }

            //off-mesh connections stored as polygons, adjust values
            int totPolyCount = polyMesh.PolyCount + storedOffMeshConCount;
            int totVertCount = polyMesh.VertCount + storedOffMeshConCount * 2;

            //find portal edges
            int edgeCount   = 0;
            int portalCount = 0;

            for (int i = 0; i < polyMesh.PolyCount; i++)
            {
                PolyMesh.Polygon p = polyMesh.Polys[i];
                for (int j = 0; j < nvp; j++)
                {
                    if (p.Vertices[j] == PolyMesh.NullId)
                    {
                        break;
                    }

                    edgeCount++;

                    if (PolyMesh.IsBoundaryEdge(p.NeighborEdges[j]))
                    {
                        int dir = p.NeighborEdges[j] % 16;
                        if (dir != 15)
                        {
                            portalCount++;
                        }
                    }
                }
            }

            int maxLinkCount = edgeCount + portalCount * 2 + offMeshConLinkCount * 2;

            //find unique detail vertices
            int uniqueDetailVertCount = 0;
            int detailTriCount        = 0;

            if (polyMeshDetail != null)
            {
                detailTriCount = polyMeshDetail.TrisCount;
                for (int i = 0; i < polyMesh.PolyCount; i++)
                {
                    int numDetailVerts = polyMeshDetail.Meshes[i].VertexCount;
                    int numPolyVerts   = polyMesh.Polys[i].VertexCount;
                    uniqueDetailVertCount += numDetailVerts - numPolyVerts;
                }
            }
            else
            {
                uniqueDetailVertCount = 0;
                detailTriCount        = 0;
                for (int i = 0; i < polyMesh.PolyCount; i++)
                {
                    int numPolyVerts = polyMesh.Polys[i].VertexCount;
                    uniqueDetailVertCount += numPolyVerts - 2;
                }
            }

            //allocate data
            header             = new PathfindingCommon.NavMeshInfo();
            navVerts           = new Vector3[totVertCount];
            navPolys           = new Poly[totPolyCount];
            navDMeshes         = new PolyMeshDetail.MeshData[polyMesh.PolyCount];
            navDVerts          = new Vector3[uniqueDetailVertCount];
            navDTris           = new PolyMeshDetail.TriangleData[detailTriCount];
            offMeshConnections = new OffMeshConnection[storedOffMeshConCount];

            //store header
            //HACK TiledNavMesh should figure out the X/Y/layer instead of the user maybe?
            header.X               = 0;
            header.Y               = 0;
            header.Layer           = 0;
            header.PolyCount       = totPolyCount;
            header.VertCount       = totVertCount;
            header.MaxLinkCount    = maxLinkCount;
            header.Bounds          = polyMesh.Bounds;
            header.DetailMeshCount = polyMesh.PolyCount;
            header.DetailVertCount = uniqueDetailVertCount;
            header.DetailTriCount  = detailTriCount;
            header.OffMeshBase     = polyMesh.PolyCount;
            header.WalkableHeight  = settings.AgentHeight;
            header.WalkableRadius  = settings.AgentRadius;
            header.WalkableClimb   = settings.MaxClimb;
            header.OffMeshConCount = storedOffMeshConCount;
            header.BvNodeCount     = settings.BuildBoundingVolumeTree ? polyMesh.PolyCount * 2 : 0;
            header.BvQuantFactor   = 1f / settings.CellSize;

            int offMeshVertsBase = polyMesh.VertCount;
            int offMeshPolyBase  = polyMesh.PolyCount;

            //store vertices
            for (int i = 0; i < polyMesh.VertCount; i++)
            {
                PolyVertex iv = polyMesh.Verts[i];
                navVerts[i].X = polyMesh.Bounds.Min.X + iv.X * settings.CellSize;
                navVerts[i].Y = polyMesh.Bounds.Min.Y + iv.Y * settings.CellHeight;
                navVerts[i].Z = polyMesh.Bounds.Min.Z + iv.Z * settings.CellSize;
            }

            //off-mesh link vertices
            int n = 0;

            for (int i = 0; i < offMeshCons.Length; i++)
            {
                //only store connections which start from this tile
                if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
                {
                    navVerts[offMeshVertsBase + (n * 2 + 0)] = offMeshCons[i].Pos0;
                    navVerts[offMeshVertsBase + (n * 2 + 1)] = offMeshCons[i].Pos1;
                    n++;
                }
            }

            //store polygons
            for (int i = 0; i < polyMesh.PolyCount; i++)
            {
                navPolys[i]           = new Poly();
                navPolys[i].VertCount = 0;
                navPolys[i].Tag       = polyMesh.Polys[i].Tag;
                navPolys[i].Area      = polyMesh.Polys[i].Area;
                navPolys[i].PolyType  = PolygonType.Ground;
                navPolys[i].Verts     = new int[nvp];
                navPolys[i].Neis      = new int[nvp];
                for (int j = 0; j < nvp; j++)
                {
                    if (polyMesh.Polys[i].Vertices[j] == PolyMesh.NullId)
                    {
                        break;
                    }

                    navPolys[i].Verts[j] = polyMesh.Polys[i].Vertices[j];
                    if (PolyMesh.IsBoundaryEdge(polyMesh.Polys[i].NeighborEdges[j]))
                    {
                        //border or portal edge
                        int dir = polyMesh.Polys[i].NeighborEdges[j] % 16;
                        if (dir == 0xf)                         //border
                        {
                            navPolys[i].Neis[j] = 0;
                        }
                        else if (dir == 0)                         //portal x-
                        {
                            navPolys[i].Neis[j] = Link.External | 4;
                        }
                        else if (dir == 1)                         //portal z+
                        {
                            navPolys[i].Neis[j] = Link.External | 2;
                        }
                        else if (dir == 2)                         //portal x+
                        {
                            navPolys[i].Neis[j] = Link.External | 0;
                        }
                        else if (dir == 3)                         //portal z-
                        {
                            navPolys[i].Neis[j] = Link.External | 6;
                        }
                    }
                    else
                    {
                        //normal connection
                        navPolys[i].Neis[j] = polyMesh.Polys[i].NeighborEdges[j] + 1;
                    }

                    navPolys[i].VertCount++;
                }
            }

            //off-mesh connection vertices
            n = 0;
            for (int i = 0; i < offMeshCons.Length; i++)
            {
                //only store connections which start from this tile
                if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
                {
                    navPolys[offMeshPolyBase + n].VertCount = 2;
                    navPolys[offMeshPolyBase + n].Verts     = new int[nvp];
                    navPolys[offMeshPolyBase + n].Verts[0]  = offMeshVertsBase + (n * 2 + 0);
                    navPolys[offMeshPolyBase + n].Verts[1]  = offMeshVertsBase + (n * 2 + 1);
                    navPolys[offMeshPolyBase + n].Tag       = offMeshCons[i].Flags;
                    navPolys[offMeshPolyBase + n].Area      = polyMesh.Polys[offMeshCons[i].Poly].Area;                //HACK is this correct?
                    navPolys[offMeshPolyBase + n].PolyType  = PolygonType.OffMeshConnection;
                    n++;
                }
            }

            //store detail meshes and vertices
            if (polyMeshDetail != null)
            {
                int            vbase             = 0;
                List <Vector3> storedDetailVerts = new List <Vector3>();
                for (int i = 0; i < polyMesh.PolyCount; i++)
                {
                    int vb             = polyMeshDetail.Meshes[i].VertexIndex;
                    int numDetailVerts = polyMeshDetail.Meshes[i].VertexCount;
                    int numPolyVerts   = navPolys[i].VertCount;
                    navDMeshes[i].VertexIndex   = vbase;
                    navDMeshes[i].VertexCount   = numDetailVerts - numPolyVerts;
                    navDMeshes[i].TriangleIndex = polyMeshDetail.Meshes[i].TriangleIndex;
                    navDMeshes[i].TriangleCount = polyMeshDetail.Meshes[i].TriangleCount;

                    //Copy detail vertices
                    //first 'nv' verts are equal to nav poly verts
                    //the rest are detail verts
                    for (int j = 0; j < navDMeshes[i].VertexCount; j++)
                    {
                        storedDetailVerts.Add(polyMeshDetail.Verts[vb + numPolyVerts + j]);
                    }

                    vbase += numDetailVerts - numPolyVerts;
                }

                navDVerts = storedDetailVerts.ToArray();

                //store triangles
                for (int j = 0; j < polyMeshDetail.TrisCount; j++)
                {
                    navDTris[j] = polyMeshDetail.Tris[j];
                }
            }
            else
            {
                //create dummy detail mesh by triangulating polys
                int tbase = 0;
                for (int i = 0; i < polyMesh.PolyCount; i++)
                {
                    int numPolyVerts = navPolys[i].VertCount;
                    navDMeshes[i].VertexIndex   = 0;
                    navDMeshes[i].VertexCount   = 0;
                    navDMeshes[i].TriangleIndex = tbase;
                    navDMeshes[i].TriangleCount = numPolyVerts - 2;

                    //triangulate polygon
                    for (int j = 2; j < numPolyVerts; j++)
                    {
                        navDTris[tbase].VertexHash0 = 0;
                        navDTris[tbase].VertexHash1 = j - 1;
                        navDTris[tbase].VertexHash2 = j;

                        //bit for each edge that belongs to the poly boundary
                        navDTris[tbase].Flags = 1 << 2;
                        if (j == 2)
                        {
                            navDTris[tbase].Flags |= 1 << 0;
                        }
                        if (j == numPolyVerts - 1)
                        {
                            navDTris[tbase].Flags |= 1 << 4;
                        }

                        tbase++;
                    }
                }
            }

            //store and create BV tree
            if (settings.BuildBoundingVolumeTree)
            {
                //build tree
                navBvTree = new BVTree(polyMesh.Verts, polyMesh.Polys, nvp, settings.CellSize, settings.CellHeight);
            }

            //store off-mesh connections
            n = 0;
            for (int i = 0; i < offMeshConnections.Length; i++)
            {
                //only store connections which start from this tile
                if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
                {
                    offMeshConnections[n].Poly = offMeshPolyBase + n;

                    //copy connection end points
                    offMeshConnections[n].Pos0 = offMeshCons[i].Pos0;
                    offMeshConnections[n].Pos1 = offMeshCons[i].Pos1;

                    offMeshConnections[n].Radius = offMeshCons[i].Radius;
                    offMeshConnections[n].Flags  = offMeshCons[i].Flags;
                    offMeshConnections[n].Side   = offMeshSides[i * 2 + 1];
                    offMeshConnections[n].Tag    = offMeshCons[i].Tag;

                    n++;
                }
            }
        }
Example #15
0
		/// <summary>
		/// Initializes a new instance of the <see cref="NavMeshBuilder" /> class.
		/// Add all the PolyMesh and PolyMeshDetail attributes to the Navigation Mesh.
		/// Then, add Off-Mesh connection support.
		/// </summary>
		/// <param name="polyMesh">The PolyMesh</param>
		/// <param name="polyMeshDetail">The PolyMeshDetail</param>
		/// <param name="offMeshCons">Offmesh connection data</param>
		/// <param name="settings">The settings used to build.</param>
		public NavMeshBuilder(PolyMesh polyMesh, PolyMeshDetail polyMeshDetail, OffMeshConnection[] offMeshCons, NavMeshGenerationSettings settings)
		{
			if (settings.VertsPerPoly > PathfindingCommon.VERTS_PER_POLYGON)
				throw new InvalidOperationException("The number of vertices per polygon is above SharpNav's limit");
			if (polyMesh.VertCount == 0)
				throw new InvalidOperationException("The provided PolyMesh has no vertices.");
			if (polyMesh.PolyCount == 0)
				throw new InvalidOperationException("The provided PolyMesh has not polys.");

			int nvp = settings.VertsPerPoly;

			//classify off-mesh connection points
			BoundarySide[] offMeshSides = new BoundarySide[offMeshCons.Length * 2];
			int storedOffMeshConCount = 0;
			int offMeshConLinkCount = 0;

			if (offMeshCons.Length > 0)
			{
				//find height bounds
				float hmin = float.MaxValue;
				float hmax = -float.MaxValue;

				if (polyMeshDetail != null)
				{
					for (int i = 0; i < polyMeshDetail.VertCount; i++)
					{
						float h = polyMeshDetail.Verts[i].Y;
						hmin = Math.Min(hmin, h);
						hmax = Math.Max(hmax, h);
					}
				}
				else
				{
					for (int i = 0; i < polyMesh.VertCount; i++)
					{
						PolyVertex iv = polyMesh.Verts[i];
						float h = polyMesh.Bounds.Min.Y + iv.Y * settings.CellHeight;
						hmin = Math.Min(hmin, h);
						hmax = Math.Max(hmax, h);
					}
				}

				hmin -= settings.MaxClimb;
				hmax += settings.MaxClimb;
				BBox3 bounds = polyMesh.Bounds;
				bounds.Min.Y = hmin;
				bounds.Max.Y = hmax;

				for (int i = 0; i < offMeshCons.Length; i++)
				{
					Vector3 p0 = offMeshCons[i].Pos0;
					Vector3 p1 = offMeshCons[i].Pos1;

					offMeshSides[i * 2 + 0] = BoundarySideExtensions.FromPoint(p0, bounds);
					offMeshSides[i * 2 + 1] = BoundarySideExtensions.FromPoint(p1, bounds);

					//off-mesh start position isn't touching mesh
					if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
					{
						if (p0.Y < bounds.Min.Y || p0.Y > bounds.Max.Y)
							offMeshSides[i * 2 + 0] = 0;
					}

					//count number of links to allocate
					if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
						offMeshConLinkCount++;
					if (offMeshSides[i * 2 + 1] == BoundarySide.Internal)
						offMeshConLinkCount++;

					if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
						storedOffMeshConCount++;
				}
			}

			//off-mesh connections stored as polygons, adjust values
			int totPolyCount = polyMesh.PolyCount + storedOffMeshConCount;
			int totVertCount = polyMesh.VertCount + storedOffMeshConCount * 2;

			//find portal edges
			int edgeCount = 0;
			int portalCount = 0;
			for (int i = 0; i < polyMesh.PolyCount; i++)
			{
				PolyMesh.Polygon p = polyMesh.Polys[i];
				for (int j = 0; j < nvp; j++)
				{
					if (p.Vertices[j] == PolyMesh.NullId)
						break;

					edgeCount++;
					
					if (PolyMesh.IsBoundaryEdge(p.NeighborEdges[j]))
					{
						int dir = p.NeighborEdges[j] % 16;
						if (dir != 15)
							portalCount++;
					}
				}
			}

			int maxLinkCount = edgeCount + portalCount * 2 + offMeshConLinkCount * 2;

			//find unique detail vertices
			int uniqueDetailVertCount = 0;
			int detailTriCount = 0;
			if (polyMeshDetail != null)
			{
				detailTriCount = polyMeshDetail.TrisCount;
				for (int i = 0; i < polyMesh.PolyCount; i++)
				{
					int numDetailVerts = polyMeshDetail.Meshes[i].VertexCount;
					int numPolyVerts = polyMesh.Polys[i].VertexCount;
					uniqueDetailVertCount += numDetailVerts - numPolyVerts;
				}
			}
			else
			{
				uniqueDetailVertCount = 0;
				detailTriCount = 0;
				for (int i = 0; i < polyMesh.PolyCount; i++)
				{
					int numPolyVerts = polyMesh.Polys[i].VertexCount;
					uniqueDetailVertCount += numPolyVerts - 2;
				}
			}

			//allocate data
			header = new PathfindingCommon.NavMeshInfo();
			navVerts = new Vector3[totVertCount];
			navPolys = new Poly[totPolyCount];
			navDMeshes = new PolyMeshDetail.MeshData[polyMesh.PolyCount];
			navDVerts = new Vector3[uniqueDetailVertCount];
			navDTris = new PolyMeshDetail.TriangleData[detailTriCount];
			offMeshConnections = new OffMeshConnection[storedOffMeshConCount];

			//store header
			//HACK TiledNavMesh should figure out the X/Y/layer instead of the user maybe?
			header.X = 0;
			header.Y = 0;
			header.Layer = 0;
			header.PolyCount = totPolyCount;
			header.VertCount = totVertCount;
			header.MaxLinkCount = maxLinkCount;
			header.Bounds = polyMesh.Bounds;
			header.DetailMeshCount = polyMesh.PolyCount;
			header.DetailVertCount = uniqueDetailVertCount;
			header.DetailTriCount = detailTriCount;
			header.OffMeshBase = polyMesh.PolyCount;
			header.WalkableHeight = settings.AgentHeight;
			header.WalkableRadius = settings.AgentRadius;
			header.WalkableClimb = settings.MaxClimb;
			header.OffMeshConCount = storedOffMeshConCount;
			header.BvNodeCount = settings.BuildBoundingVolumeTree ? polyMesh.PolyCount * 2 : 0;
			header.BvQuantFactor = 1f / settings.CellSize;

			int offMeshVertsBase = polyMesh.VertCount;
			int offMeshPolyBase = polyMesh.PolyCount;

			//store vertices
			for (int i = 0; i < polyMesh.VertCount; i++)
			{
				PolyVertex iv = polyMesh.Verts[i];
				navVerts[i].X = polyMesh.Bounds.Min.X + iv.X * settings.CellSize;
				navVerts[i].Y = polyMesh.Bounds.Min.Y + iv.Y * settings.CellHeight;
				navVerts[i].Z = polyMesh.Bounds.Min.Z + iv.Z * settings.CellSize;
			}

			//off-mesh link vertices
			int n = 0;
			for (int i = 0; i < offMeshCons.Length; i++)
			{
				//only store connections which start from this tile
				if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
				{
					navVerts[offMeshVertsBase + (n * 2 + 0)] = offMeshCons[i].Pos0;
					navVerts[offMeshVertsBase + (n * 2 + 1)] = offMeshCons[i].Pos1;
					n++;
				}
			}

			//store polygons
			for (int i = 0; i < polyMesh.PolyCount; i++)
			{
				navPolys[i] = new Poly();
				navPolys[i].VertCount = 0;
				navPolys[i].Tag = polyMesh.Polys[i].Tag;
				navPolys[i].Area = polyMesh.Polys[i].Area;
				navPolys[i].PolyType = PolygonType.Ground;
				navPolys[i].Verts = new int[nvp];
				navPolys[i].Neis = new int[nvp];
				for (int j = 0; j < nvp; j++)
				{
					if (polyMesh.Polys[i].Vertices[j] == PolyMesh.NullId)
						break;

					navPolys[i].Verts[j] = polyMesh.Polys[i].Vertices[j];
					if (PolyMesh.IsBoundaryEdge(polyMesh.Polys[i].NeighborEdges[j]))
					{
						//border or portal edge
						int dir = polyMesh.Polys[i].NeighborEdges[j] % 16;
						if (dir == 0xf) //border
							navPolys[i].Neis[j] = 0;
						else if (dir == 0) //portal x-
							navPolys[i].Neis[j] = Link.External | 4;
						else if (dir == 1) //portal z+
							navPolys[i].Neis[j] = Link.External | 2;
						else if (dir == 2) //portal x+
							navPolys[i].Neis[j] = Link.External | 0;
						else if (dir == 3) //portal z-
							navPolys[i].Neis[j] = Link.External | 6;
					}
					else
					{
						//normal connection
						navPolys[i].Neis[j] = polyMesh.Polys[i].NeighborEdges[j] + 1;
					}

					navPolys[i].VertCount++;
				}
			}

			//off-mesh connection vertices
			n = 0;
			for (int i = 0; i < offMeshCons.Length; i++)
			{
				//only store connections which start from this tile
				if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
				{
					navPolys[offMeshPolyBase + n].VertCount = 2;
					navPolys[offMeshPolyBase + n].Verts = new int[nvp];
					navPolys[offMeshPolyBase + n].Verts[0] = offMeshVertsBase + (n * 2 + 0);
					navPolys[offMeshPolyBase + n].Verts[1] = offMeshVertsBase + (n * 2 + 1);
					navPolys[offMeshPolyBase + n].Tag = offMeshCons[i].Flags;
					navPolys[offMeshPolyBase + n].Area = polyMesh.Polys[offMeshCons[i].Poly].Area; //HACK is this correct?
					navPolys[offMeshPolyBase + n].PolyType = PolygonType.OffMeshConnection;
					n++;
				}
			}
			
			//store detail meshes and vertices
			if (polyMeshDetail != null)
			{
				int vbase = 0;
				List<Vector3> storedDetailVerts = new List<Vector3>();
				for (int i = 0; i < polyMesh.PolyCount; i++)
				{
					int vb = polyMeshDetail.Meshes[i].VertexIndex;
					int numDetailVerts = polyMeshDetail.Meshes[i].VertexCount;
					int numPolyVerts = navPolys[i].VertCount;
					navDMeshes[i].VertexIndex = vbase;
					navDMeshes[i].VertexCount = numDetailVerts - numPolyVerts;
					navDMeshes[i].TriangleIndex = polyMeshDetail.Meshes[i].TriangleIndex;
					navDMeshes[i].TriangleCount = polyMeshDetail.Meshes[i].TriangleCount;
					
					//Copy detail vertices 
					//first 'nv' verts are equal to nav poly verts
					//the rest are detail verts
					for (int j = 0; j < navDMeshes[i].VertexCount; j++)
					{
						storedDetailVerts.Add(polyMeshDetail.Verts[vb + numPolyVerts + j]);
					}

					vbase += numDetailVerts - numPolyVerts;
				}

				navDVerts = storedDetailVerts.ToArray();

				//store triangles
				for (int j = 0; j < polyMeshDetail.TrisCount; j++)
					navDTris[j] = polyMeshDetail.Tris[j];
			}
			else
			{
				//create dummy detail mesh by triangulating polys
				int tbase = 0;
				for (int i = 0; i < polyMesh.PolyCount; i++)
				{
					int numPolyVerts = navPolys[i].VertCount;
					navDMeshes[i].VertexIndex = 0;
					navDMeshes[i].VertexCount = 0;
					navDMeshes[i].TriangleIndex = tbase;
					navDMeshes[i].TriangleCount = numPolyVerts - 2;

					//triangulate polygon
					for (int j = 2; j < numPolyVerts; j++)
					{
						navDTris[tbase].VertexHash0 = 0;
						navDTris[tbase].VertexHash1 = j - 1;
						navDTris[tbase].VertexHash2 = j;

						//bit for each edge that belongs to the poly boundary
						navDTris[tbase].Flags = 1 << 2;
						if (j == 2) 
							navDTris[tbase].Flags |= 1 << 0;
						if (j == numPolyVerts - 1)
							navDTris[tbase].Flags |= 1 << 4;
						
						tbase++;
					}
				}
			}
			
			//store and create BV tree
			if (settings.BuildBoundingVolumeTree)
			{
				//build tree
				navBvTree = new BVTree(polyMesh.Verts, polyMesh.Polys, nvp, settings.CellSize, settings.CellHeight);
			}

			//store off-mesh connections
			n = 0;
			for (int i = 0; i < offMeshConnections.Length; i++)
			{
				//only store connections which start from this tile
				if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
				{
					offMeshConnections[n].Poly = offMeshPolyBase + n;

					//copy connection end points
					offMeshConnections[n].Pos0 = offMeshCons[i].Pos0;
					offMeshConnections[n].Pos1 = offMeshCons[i].Pos1;

					offMeshConnections[n].Radius = offMeshCons[i].Radius;
					offMeshConnections[n].Flags = offMeshCons[i].Flags;
					offMeshConnections[n].Side = offMeshSides[i * 2 + 1];
					offMeshConnections[n].Tag = offMeshCons[i].Tag;

					n++;
				}
			}
		}
Example #16
0
        /// <summary>
        /// Contacts between two chains
        /// update the treeB when it is necessary
        /// </summary>
        /// <param name="treeA">center tree</param>
        /// <param name="treeB">the tree need to be translated by translateVectorA</param>
        /// <param name="translateVectorA"></param>
        public void Intersect(BVTree treeA, BVTree treeB, double[] translateVectorA)
        {
            if (treeA == null || treeB == null)
            {
                return;
            }
            BoundingBox bb = treeB.Root.BoundBox.UpdateBoundingBox(translateVectorA);

            if (!treeA.Root.BoundBox.MayOverlap(bb, AppSettings.parameters.contactParams.cutoffAtomDist))
            {
                return;
            }
            // if it is a leaf node of tree A
            if (treeA.LeftBranch == null && treeA.RightBranch == null)
            {
                // it is a leaf node of tree B
                if (treeB.LeftBranch == null && treeB.RightBranch == null)
                {
                    Node leafNode = new Node(treeB.Root);
                    leafNode.UpdateLeafNode(translateVectorA);
                    foreach (AtomInfo atomA in treeA.Root.AtomList)
                    {
                        foreach (AtomInfo atomB in leafNode.AtomList)
                        {
                            float atomDist = (float)(atomA - atomB);
                            // if distance is less than the threshold
                            // possible atomic contact
                            if (atomDist < AppSettings.parameters.contactParams.cutoffAtomDist)
                            {
                                AtomPair atomPair = new AtomPair();
                                atomPair.firstAtom  = atomA;
                                atomPair.secondAtom = atomB;
                                atomPair.distance   = atomDist;
                                string seqIdString = atomA.seqId + "_" + atomB.seqId;
                                if (!chainContactInfo.atomContactHash.ContainsKey(seqIdString))
                                {
                                    chainContactInfo.atomContactHash.Add(seqIdString, atomPair);
                                }
                                else
                                {
                                    // give priority to Cbeta
                                    if (atomPair.firstAtom.atomName == "CB" && atomPair.secondAtom.atomName == "CB")
                                    {
                                        chainContactInfo.atomContactHash[seqIdString] = atomPair;
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    Intersect(treeA, treeB.LeftBranch, translateVectorA);
                    Intersect(treeA, treeB.RightBranch, translateVectorA);
                }
            }
            else
            {
                Intersect(treeA.LeftBranch, treeB, translateVectorA);
                Intersect(treeA.RightBranch, treeB, translateVectorA);
            }
        }
Example #17
0
        /// <summary>
        /// Contacts between two chains
        /// update the treeB when it is necessary
        /// </summary>
        /// <param name="treeA">center tree</param>
        /// <param name="treeB">the tree need to be translated by translateVectorA</param>
        /// <param name="translateVectorA"></param>
        private void IntersectResidues(BVTree treeA, BVTree treeB)
        {
            if (!treeA.Root.BoundBox.MayOverlap
                    (treeB.Root.BoundBox, AppSettings.parameters.contactParams.cutoffResidueDist))
            {
                return;
            }
            // if it is a leaf node of tree A
            if (treeA.LeftBranch == null && treeA.RightBranch == null)
            {
                // it is a leaf node of tree B
                if (treeB.LeftBranch == null && treeB.RightBranch == null)
                {
                    foreach (AtomInfo atomA in treeA.Root.AtomList)
                    {
                        foreach (AtomInfo atomB in treeB.Root.AtomList)
                        {
                            float atomDist = (float)(atomA - atomB);
                            if ((atomA.atomName == "CB" || atomA.atomName == "CA") &&
                                (atomB.atomName == "CB" || atomB.atomName == "CA") &&
                                atomDist < AppSettings.parameters.contactParams.cutoffResidueDist)
                            {
                                AtomPair atomPair = new AtomPair();
                                atomPair.firstAtom  = atomA;
                                atomPair.secondAtom = atomB;
                                atomPair.distance   = atomDist;
                                string seqIdString = atomA.seqId + "_" + atomB.seqId;
                                if (!chainContactInfo.cbetaContactHash.ContainsKey(seqIdString))
                                {
                                    chainContactInfo.cbetaContactHash.Add(seqIdString, atomPair);
                                }
                                else
                                {
                                    // give priority to Cbeta then Calpha

                                    /*				if (atomPair.firstAtom.atomName == "CB" && atomPair.secondAtom.atomName == "CB")
                                     *                              {
                                     *                                      chainContactInfo.cbetaContactHash[seqIdString] = atomPair;
                                     *                              }*/
                                    // minimum distance between bb atoms
                                    double dist = ((AtomPair)chainContactInfo.cbetaContactHash[seqIdString]).distance;
                                    if (dist > atomDist)
                                    {
                                        chainContactInfo.cbetaContactHash[seqIdString] = atomPair;
                                    }
                                }
                            }
                            // if distance is less than the threshold
                            // atomic contact
                            if (atomDist < AppSettings.parameters.contactParams.cutoffAtomDist)
                            {
                                string seqIdString = atomA.seqId + "_" + atomB.seqId;
                                if (!chainContactInfo.atomContactHash.ContainsKey(seqIdString))
                                {
                                    AtomPair atomPair = new AtomPair();
                                    atomPair.firstAtom  = atomA;
                                    atomPair.secondAtom = atomB;
                                    atomPair.distance   = atomDist;
                                    chainContactInfo.atomContactHash.Add(seqIdString, atomPair);
                                }
                                else
                                {
                                    // find the atom pair with minimum distance
                                    AtomPair atomPair = (AtomPair)chainContactInfo.atomContactHash[seqIdString];
                                    if (atomDist < atomPair.distance)
                                    {
                                        atomPair.firstAtom  = atomA;
                                        atomPair.secondAtom = atomB;
                                        atomPair.distance   = atomDist;
                                        chainContactInfo.atomContactHash[seqIdString] = atomPair;
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    IntersectResidues(treeA, treeB.LeftBranch);
                    IntersectResidues(treeA, treeB.RightBranch);
                }
            }
            else
            {
                IntersectResidues(treeA.LeftBranch, treeB);
                IntersectResidues(treeA.RightBranch, treeB);
            }
        }