/// <summary> /// Reads a cluster centre from a binary file. /// </summary> /// <param name="fileIn">The input file.</param> /// <param name="coordCount">The number of vertex coordinates to read.</param> /// <returns>Returns the read centre.</returns> public static Centre ReadBinary(System.IO.BinaryReader fileIn, ushort coordCount) { // check that we are loading the right types System.Diagnostics.Debug.Assert(FileAddressSize == sizeof(long)); System.Diagnostics.Debug.Assert(ChildrenCountSize == sizeof(int)); // create the cluster centre Centre c = new Centre(); // read the vertex coordinates c.vertex = Vertex.ReadBinary(fileIn, coordCount); // read children information c.childrenFileStart = fileIn.ReadInt64(); c.childrenCount = fileIn.ReadInt32(); return(c); }
/// <summary> /// Loads all members of the given cluster. /// </summary> /// <param name="level">The level from where to load the members (one level lower than the cluster centre).</param> /// <param name="startIndex">Index of the first cluster member.</param> /// <param name="count">Number of the cluster members.</param> /// <returns>Returns an array of cluster vertices.</returns> public Centre[] ExpandCluster(int level, long startIndex, int count) { // open input file string fileName = GetNumberedFileName(level); FileStream streamIn = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); BinaryReader fileIn = new BinaryReader(streamIn); // read the number of coordinates each vertex has ushort coordCount = fileIn.ReadUInt16(); // seek to the appropriate cluster streamIn.Seek(startIndex, SeekOrigin.Begin); // prepare memory Centre[] clusterMembers = new Centre[count]; // load the cluster members if (level > 0) { for (int i = 0; i < count; i++) { clusterMembers[i] = Centre.ReadBinary(fileIn, coordCount); } } else { for (int i = 0; i < count; i++) { clusterMembers[i] = Centre.ReadBinaryJustCoords(fileIn, coordCount); } } // close input file fileIn.Close(); streamIn.Close(); return(clusterMembers); }
/// <summary> /// Adds more centres for clustering. /// </summary> /// <param name="centres">The centres to add.</param> /// <param name="level">The level where to add.</param> private void PushVertices(Centre[] centres, int level) { if (finished) { throw new ApplicationException("The input stream has already been finished."); } // get the appropriate clustering level ClusteringLevel cl = clusteringLevels[level]; // is there enough free space? if (centres.Length <= cl.FreeSpace) { // yes, add all the vertices right away cl.PushVertices(centres); } else { // no, add the vertices by pieces int remainToPush = centres.Length; int alreadyPushed = 0; int free = cl.FreeSpace; // prepare the first piece Centre[] pieceToPush = new Centre[free]; Array.Copy(centres, alreadyPushed, pieceToPush, 0, free); // push the first piece cl.PushVertices(pieceToPush); remainToPush -= free; alreadyPushed += free; // process the full block ProcessLevel(level); pieceToPush = new Centre[blockSize]; // push further pieces while (remainToPush > blockSize) { // prepare a single piece Array.Copy(centres, alreadyPushed, pieceToPush, 0, blockSize); // push the piece cl.PushVertices(pieceToPush); remainToPush -= blockSize; alreadyPushed += blockSize; // process the full block ProcessLevel(level); } // copy the last remaining piece pieceToPush = new Centre[remainToPush]; Array.Copy(centres, alreadyPushed, pieceToPush, 0, remainToPush); // push the last remaining piece cl.PushVertices(pieceToPush); } // check whether there is still some space for further vertices if (cl.FreeSpace == 0) { // no, the level is exactly full, let's process it ProcessLevel(level); } }