public LayoutLevel(string name, int modulo, List <LayoutLevel> levels) { this.modulo = modulo; LayoutLevel child = levels[levels.Count - 1]; this.chunk_size = child.modulo * child.chunk_size; this.padding = 6 * (int)Math.Pow(3, levels.Count - 2); // third level (count=2) should be 6, then 18 LayoutLevel lastParallel = levels[levels.Count - 2]; this.thickness = lastParallel.modulo * lastParallel.thickness + padding; }
public int[] position_on_screen(long index) { int[] xy = new int[] { 0, 0 }; for (int i = 0; i < this.levels.Count; ++i) { LayoutLevel level = this.levels[i]; int part = i % 2; int coordinate_in_chunk = ((int)(index / level.chunk_size)) % level.modulo; xy[part] += level.thickness * coordinate_in_chunk; } return(xy); }
public long index_from_screen(int x, int y) { long index_from_xy = 0; int[] xy_remaining = { x, y }; for (int i = this.levels.Count - 1; i >= 0; --i) //reverse { LayoutLevel level = this.levels[i]; int part = i % 2; int number_of_full_increments = (int)(xy_remaining[part] / level.thickness); index_from_xy += level.chunk_size * number_of_full_increments; // add total nulceotide size for every full increment of this level e.g. Tile Y height xy_remaining[part] -= number_of_full_increments * level.thickness; //subtract the credited coordinates to shift to relative coordinates in that level } return(index_from_xy); }
/** Similar to position_on_screen(index) but it instead returns the largest x and y values that the layout will need from * any index in between 0 and last_index. */ public int[] max_dimensions(long last_index, bool multipart_file) { if (multipart_file) { last_index *= 2; //this is a guesstimation of the amount of extra pixel layout area will be needed for padding between contigs } int[] xy = new int[] { 0, 0 }; for (int i = 0; i < this.levels.Count; ++i) { LayoutLevel level = this.levels[i]; int part = i % 2; int coordinate_in_chunk = Math.Min((int)(Math.Ceiling(last_index / (double)level.chunk_size)), level.modulo); //how many of these will you need up to a full modulo worth if (coordinate_in_chunk > 1) { xy[part] = Math.Max(xy[part], level.thickness * coordinate_in_chunk); // not cumulative, just take the max size for either x or y } } return(xy); }
private long[] paddingInNucleotides(long totalProgress, long nextSegmentLength, int nContigs, bool multipart_file) { int min_gap = (20 + 6) * 100; //20px font height, + 6px vertical padding * 100 nt per line if (!multipart_file) { return(new long[] { 0, 0, 0 }); } for (int i = 0; i < this.levels.Count; ++i) { if (nextSegmentLength + min_gap < levels[i].chunk_size) { long title_padding = Math.Max(min_gap, levels[i - 1].chunk_size); // give a full level of blank space just in case the previous long space_remaining = levels[i].chunk_size - totalProgress % levels[i].chunk_size; // sequence comes right up to the edge. There should always be >= 1 full gap LayoutLevel reset_level = nextSegmentLength + title_padding > space_remaining ? levels[i] : levels[i - 1]; //bigger reset when close to filling chunk_size long reset_padding = totalProgress == 0 ? 0 : reset_level.chunk_size - totalProgress % reset_level.chunk_size; // fill out the remainder so we can start at the beginning long tail = levels[i - 1].chunk_size - (totalProgress + title_padding + reset_padding + nextSegmentLength) % levels[i - 1].chunk_size - 1; return(new long[] { title_padding, tail, reset_padding }); } } return(new long[] { 0, 0, 0 }); }