X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Frenderer%2FContactGeometry.java;h=42dde8d07a5e828aee9f20da1fc1ad7975ff128d;hb=cc36e0cc33145e21186643a28b975be1a01d2d55;hp=9fd4de6cd02c2502ca94cfb106c4ab2c2d5059d4;hpb=80b889f0cca49103e1b20ed806755a0719789906;p=jalview.git diff --git a/src/jalview/renderer/ContactGeometry.java b/src/jalview/renderer/ContactGeometry.java index 9fd4de6..42dde8d 100644 --- a/src/jalview/renderer/ContactGeometry.java +++ b/src/jalview/renderer/ContactGeometry.java @@ -1,6 +1,28 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ package jalview.renderer; +import java.util.Arrays; import java.util.Iterator; +import java.util.List; import jalview.datamodel.ColumnSelection; import jalview.datamodel.ContactListI; @@ -19,21 +41,47 @@ public class ContactGeometry final ContactListI contacts; + /** + * how many pixels per contact (1..many) + */ final int pixels_step; + /** + * how many contacts per pixel (many > 0) + */ final double contacts_per_pixel; + /** + * number of contacts being mapped + */ final int contact_height; + /** + * number of pixels to map contact_height to + */ final int graphHeight; + /** + * number of contacts for each pixel_step - to last whole contact + */ + final double contacts_step; + + final int lastStep; + + /** + * Bean used to map from a range of contacts to a range of pixels + * + * @param contacts + * @param graphHeight + * Number of pixels to map given range of contacts + */ public ContactGeometry(final ContactListI contacts, int graphHeight) { this.contacts = contacts; this.graphHeight = graphHeight; contact_height = contacts.getContactHeight(); // fractional number of contacts covering each pixel - contacts_per_pixel = (graphHeight < 1) ? contact_height + contacts_per_pixel = (graphHeight <= 1) ? contact_height : ((double) contact_height) / ((double) graphHeight); if (contacts_per_pixel >= 1) @@ -47,6 +95,9 @@ public class ContactGeometry pixels_step = (int) Math .ceil(((double) graphHeight) / (double) contact_height); } + contacts_step = pixels_step * contacts_per_pixel; + lastStep = (int) Math.min((double) graphHeight, + ((double) graphHeight) / ((double) pixels_step)); } public class contactInterval @@ -69,6 +120,24 @@ public class ContactGeometry public final int pEnd; + @Override + public boolean equals(Object obj) + { + if (obj == null || !(obj instanceof contactInterval)) + { + return false; + } + contactInterval them = (contactInterval) obj; + return cStart == them.cStart && cEnd == them.cEnd && pEnd == them.pEnd + && pStart == them.pStart; + } + + @Override + public String toString() + { + return "Contacts [" + cStart + "," + cEnd + "] : Pixels [" + pStart + + "," + pEnd + "]"; + } } /** @@ -100,7 +169,7 @@ public class ContactGeometry { // TODO: turn into function on hiddenColumns and create test !! Iterator viscont = hiddenColumns.getVisContigsIterator( - mappedRange[p], mappedRange[p + 1], false); + -1 + mappedRange[p], -1 + mappedRange[p + 1], false); containsHidden = !viscont.hasNext(); if (!containsHidden) { @@ -112,8 +181,8 @@ public class ContactGeometry } else { - rowsel = columnSelection.intersects(mappedRange[p], - mappedRange[p + 1]); + rowsel = columnSelection.intersects(-1 + mappedRange[p], + -1 + mappedRange[p + 1]); } } return rowsel; @@ -121,21 +190,56 @@ public class ContactGeometry } /** + * Return mapped cell intersecting pStart \ + * + * FIXME: REDUNDANT METHOD - COULD DELETE FIXME: OR RE-IMPLEMENT AS EFFICIENT + * RANGE QUERY * * @param pStart + * [0..) * @param pEnd - * @return range for + * @return nearest full cell containing pStart - does not set + * contactInterval.pEnd or cEnd to equivalent position on pEnd ! */ public contactInterval mapFor(int pStart, int pEnd) { - int cStart = (int) Math.floor(pStart * contacts_per_pixel); - contactInterval ci = new contactInterval(cStart, - (int) Math.min(contact_height, - Math.ceil( - cStart + (pEnd - pStart) * contacts_per_pixel)), - pStart, pEnd); - - return ci; + if (pStart < 0) + { + pStart = 0; + } + if (pEnd < pStart) + { + pEnd = pStart; + } + if (pEnd >= graphHeight) + { + pEnd = graphHeight - 1; + } + if (pStart >= graphHeight) + { + pStart = graphHeight - pixels_step; + } + int step = Math.floorDiv(pStart, pixels_step); + return findStep(step); + } + + /** + * + * @param step + * [0..) n steps covering height and contactHeight + * @return contactInterval for step, or null if out of bounds + */ + contactInterval findStep(int step) + { + if (step < 0 || step > lastStep) + { + return null; + } + return new contactInterval((int) Math.floor(contacts_step * step), + -1 + (int) Math.min(contact_height, + Math.floor(contacts_step * (step + 1))), + pixels_step * step, + Math.min(graphHeight, (step + 1) * pixels_step) - 1); } /** @@ -146,15 +250,31 @@ public class ContactGeometry */ public contactInterval mapFor(int pCentre) { - int pStart = Math.max(pCentre - pixels_step, 0); - int pEnd = Math.min(pStart + pixels_step, graphHeight); - int cStart = (int) Math.floor(pStart * contacts_per_pixel); - contactInterval ci = new contactInterval(cStart, - (int) Math.min(contact_height, - Math.ceil(cStart + (pixels_step) * contacts_per_pixel)), - pStart, pEnd); - - return ci; + if (pCentre >= graphHeight + pixels_step) + { + return null; + } + int step = Math.floorDiv(pCentre, pixels_step); + return findStep(step); + } + + public List allSteps() + { + contactInterval[] array = new contactInterval[lastStep + 1]; + int csum = 0, psum = 0; + for (int i = 0; i <= lastStep; i++) + { + array[i] = findStep(i); + csum += 1 + array[i].cEnd - array[i].cStart; + psum += 1 + array[i].pEnd - array[i].pStart; + } + if (csum != contact_height || psum != graphHeight) + { + System.err.println("csum = " + csum + " not " + contact_height + "\n" + + "psum = " + psum + " not " + graphHeight); + return null; + } + return Arrays.asList(array); } public Iterator iterateOverContactIntervals(