X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Frenderer%2FContactGeometry.java;h=a1443c82cec29f357abfe974f60cf85a24821eab;hb=f047ab25cc45bfc9d130f67d2c56a940751d9c91;hp=9fd4de6cd02c2502ca94cfb106c4ab2c2d5059d4;hpb=985903ad810d9ef6ba0d09ff2b29d24e22c0708d;p=jalview.git diff --git a/src/jalview/renderer/ContactGeometry.java b/src/jalview/renderer/ContactGeometry.java index 9fd4de6..a1443c8 100644 --- a/src/jalview/renderer/ContactGeometry.java +++ b/src/jalview/renderer/ContactGeometry.java @@ -1,6 +1,8 @@ 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 +21,45 @@ 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 +73,8 @@ 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 +97,22 @@ 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 +144,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 +156,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 +165,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 +225,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(