Revision 8281 trunk/libraries/libCq CMS for java.old/src/org/cresques/px/PxRaster.java
PxRaster.java | ||
---|---|---|
27 | 27 |
import java.awt.Component; |
28 | 28 |
import java.awt.Graphics2D; |
29 | 29 |
import java.awt.Image; |
30 |
import java.awt.geom.AffineTransform; |
|
30 | 31 |
import java.awt.geom.GeneralPath; |
32 |
import java.awt.geom.NoninvertibleTransformException; |
|
31 | 33 |
import java.awt.geom.Point2D; |
32 | 34 |
import java.awt.image.BufferedImage; |
33 | 35 |
import java.awt.image.DataBuffer; |
... | ... | |
88 | 90 |
private RasterFilterStackManager stackManager = null; |
89 | 91 |
private Image geoImage = null; |
90 | 92 |
private ViewPortData lastViewPort = null; |
93 |
|
|
94 |
/** |
|
95 |
* Variable usada por el draw para calcular el n?mero de pixeles a leer de un |
|
96 |
* raster rotado. |
|
97 |
*/ |
|
98 |
private double[] adjustedRotedExtent = null; |
|
91 | 99 |
|
92 | 100 |
/** |
93 | 101 |
* Constructor. |
... | ... | |
110 | 118 |
this.proj = proj; |
111 | 119 |
this.component = component; |
112 | 120 |
setExtent(geoFile[0].getExtent()); |
121 |
setExtentForRequest(geoFile[0].getExtentForRequest()); |
|
113 | 122 |
geoFile[0].setView(geoFile[0].getExtent()); |
114 | 123 |
extentOrig = extent; |
115 | 124 |
bandSwitch.addFile(geoFile[0]); |
... | ... | |
142 | 151 |
geoFile[i] = GeoRasterFile.openFile(proj, fnames[i]); //loadECW(fname); |
143 | 152 |
geoFile[i].setUpdatable((Component) component); |
144 | 153 |
setExtent(geoFile[i].getExtent()); |
154 |
setExtentForRequest(geoFile[i].getExtentForRequest()); |
|
145 | 155 |
geoFile[i].setView(geoFile[i].getExtent()); |
146 | 156 |
bandSwitch.addFile(geoFile[i]); |
147 | 157 |
} |
... | ... | |
167 | 177 |
this.component = component; |
168 | 178 |
|
169 | 179 |
setExtent(geoFile[0].getExtent()); |
180 |
setExtentForRequest(geoFile[0].getExtentForRequest()); |
|
170 | 181 |
if(view != null){ |
171 | 182 |
geoFile[0].setView(view); //geoFile.getExtent()); |
172 | 183 |
extentOrig = extent; |
... | ... | |
203 | 214 |
listFiles[geoFile.length] = GeoRasterFile.openFile(proj, fileName); |
204 | 215 |
listFiles[geoFile.length].setUpdatable((Component) component); |
205 | 216 |
setExtent(listFiles[geoFile.length].getExtent()); |
217 |
setExtentForRequest(listFiles[geoFile.length].getExtentForRequest()); |
|
206 | 218 |
listFiles[geoFile.length].setView(listFiles[geoFile.length].getExtent()); |
207 | 219 |
bandSwitch.addFile(listFiles[geoFile.length]); |
208 | 220 |
geoFile = listFiles; |
... | ... | |
626 | 638 |
} |
627 | 639 |
|
628 | 640 |
/** |
641 |
* Asigna el extent sobre el que se ajusta una petici?n para que esta no exceda el |
|
642 |
* extent m?ximo del raster. Para un raster sin rotar ser? igual al extent |
|
643 |
* pero para un raster rotado ser? igual al extent del raster como si no |
|
644 |
* tuviera rotaci?n. Esto ha de ser as? ya que la rotaci?n solo se hace sobre la |
|
645 |
* vista y las peticiones han de hacerse en coordenadas de la imagen sin shearing |
|
646 |
* aplicado. |
|
647 |
* @param Extent |
|
648 |
*/ |
|
649 |
public void setExtentForRequest(Extent e) { |
|
650 |
super.requestExtent = e; |
|
651 |
if(e != null){ |
|
652 |
pts = new Vector(); |
|
653 |
pts.add(proj.createPoint(e.minX(), e.minY())); |
|
654 |
pts.add(proj.createPoint(e.maxX(), e.minY())); |
|
655 |
pts.add(proj.createPoint(e.maxX(), e.maxY())); |
|
656 |
pts.add(proj.createPoint(e.minX(), e.maxY())); |
|
657 |
} |
|
658 |
} |
|
659 |
|
|
660 |
/** |
|
629 | 661 |
* Cambia la vista (viewport) sobre el raster. |
630 | 662 |
* |
631 | 663 |
* @param v extent |
... | ... | |
668 | 700 |
} |
669 | 701 |
|
670 | 702 |
/** |
703 |
* Transforma la petici?n que est? en coordenadas de la imagen sin rotar a coordenadas de la imagen rotada |
|
704 |
* para que sea posible el calculo de la caja m?nima de inclusi?n. La coordenada superior izquierda de esta |
|
705 |
* ser? la que se use para posicionar la imagen sobre el graphics aplicandole la transformaci?n de la la vista. |
|
706 |
* @param v |
|
707 |
* @return |
|
708 |
*/ |
|
709 |
private Point2D coordULRotateRaster(double[] v){ |
|
710 |
double vx = v[0]; |
|
711 |
double vy = v[1]; |
|
712 |
double vx2 = v[2]; |
|
713 |
double vy2 = v[3]; |
|
714 |
if (geoFile != null) { |
|
715 |
double[] transf = geoFile[0].getTransform(); |
|
716 |
|
|
717 |
if(transf != null && (transf[2] != 0 || transf[4] != 0)){ |
|
718 |
//La transformaci?n se hace en base a una esquina que varia con el signo del |
|
719 |
//pixel size. |
|
720 |
double ptoDesplX = (transf[1] > 0)?requestExtent.minX():requestExtent.maxX(); |
|
721 |
double ptoDesplY = (transf[5] < 0)?requestExtent.maxY():requestExtent.minY(); |
|
722 |
|
|
723 |
Point2D ul = new Point2D.Double(vx - ptoDesplX, vy2 - ptoDesplY); |
|
724 |
Point2D ur = new Point2D.Double(vx2 - ptoDesplX, vy2 - ptoDesplY); |
|
725 |
Point2D ll = new Point2D.Double(vx - ptoDesplX, vy - ptoDesplY); |
|
726 |
Point2D lr = new Point2D.Double(vx2 - ptoDesplX, vy - ptoDesplY); |
|
727 |
|
|
728 |
double shearX = 0; |
|
729 |
double shearY = 0; |
|
730 |
|
|
731 |
if(transf[5] != 0) |
|
732 |
shearX = transf[2] / transf[5]; |
|
733 |
else |
|
734 |
shearX = transf[2]; |
|
735 |
if(transf[1] != 0) |
|
736 |
shearY = transf[4] / transf[1]; |
|
737 |
else |
|
738 |
shearY = transf[4]; |
|
739 |
|
|
740 |
|
|
741 |
AffineTransform at = new AffineTransform(); |
|
742 |
at.setToShear(shearX, shearY); |
|
743 |
|
|
744 |
at.transform(ul, ul); |
|
745 |
at.transform(ur, ur); |
|
746 |
at.transform(ll, ll); |
|
747 |
at.transform(lr, lr); |
|
748 |
|
|
749 |
ul = new Point2D.Double(ul.getX() + ptoDesplX, ul.getY() + ptoDesplY); |
|
750 |
ur = new Point2D.Double(ur.getX() + ptoDesplX, ur.getY() + ptoDesplY); |
|
751 |
ll = new Point2D.Double(ll.getX() + ptoDesplX, ll.getY() + ptoDesplY); |
|
752 |
lr = new Point2D.Double(lr.getX() + ptoDesplX, lr.getY() + ptoDesplY); |
|
753 |
|
|
754 |
vx2 = Math.max(Math.max(ul.getX(), ur.getX()), Math.max(ll.getX(), lr.getX())); |
|
755 |
vy2 = Math.max(Math.max(ul.getY(), ur.getY()), Math.max(ll.getY(), lr.getY())); |
|
756 |
vx = Math.min(Math.min(ul.getX(), ur.getX()), Math.min(ll.getX(), lr.getX())); |
|
757 |
vy = Math.min(Math.min(ul.getY(), ur.getY()), Math.min(ll.getY(), lr.getY())); |
|
758 |
adjustedRotedExtent = new double[4]; |
|
759 |
adjustedRotedExtent[0] = vx; |
|
760 |
adjustedRotedExtent[1] = vy; |
|
761 |
adjustedRotedExtent[2] = vx2; |
|
762 |
adjustedRotedExtent[3] = vy2; |
|
763 |
return ul; |
|
764 |
} |
|
765 |
|
|
766 |
} |
|
767 |
return null; |
|
768 |
|
|
769 |
} |
|
770 |
|
|
771 |
/** |
|
671 | 772 |
* Ajusta la extensi?n pasada por par?metro y que corresponde al extent de la vista donde |
672 | 773 |
* se va a dibujar a los valores m?ximos y m?nimos de la imagen. Esto sirve para que la |
673 | 774 |
* petici?n al driver nunca sobrepase los l?mites de la imagen tratada aunque la vista |
674 | 775 |
* donde se dibuje sea de mayor tama?o. |
675 | 776 |
* |
777 |
* Antes de realizar este ajuste hay que transformar la petici?n que puede corresponder a |
|
778 |
* una imagen rotada a las coordenadas de la imagen sin rotar ya que las peticiones al |
|
779 |
* driver hay que hacerlas con estas coordenadas. Para esto trasladamos la petici?n al origen |
|
780 |
* de la imagen (esquina superior izquierda), aplicamos la transformaci?n inversa a las cuatro |
|
781 |
* esquinas obtenidas y volvemos a trasladar a su posici?n original. |
|
782 |
* |
|
783 |
* Se usa la transformaci?n inversa para trasladar un punto del raster rotado al mismo sin |
|
784 |
* rotar y la transformaci?n af?n normal para trasladar un punto sin rotar a uno rotado. |
|
785 |
* |
|
676 | 786 |
* @param sz Extent completo de la vista donde se va a dibujar. |
677 | 787 |
*/ |
678 |
protected double[] calculateNewView(Extent sz) { |
|
788 |
protected double[] calculateNewView(ViewPortData vp) { |
|
789 |
Extent sz = vp.getExtent(); |
|
679 | 790 |
double vx = sz.minX(); |
680 | 791 |
double vy = sz.minY(); |
681 | 792 |
double vx2 = sz.maxX(); |
682 | 793 |
double vy2 = sz.maxY(); |
794 |
|
|
795 |
//Trasladamos la petici?n si est? rotada a su posici?n sin rotar |
|
796 |
|
|
797 |
if (geoFile != null) { |
|
798 |
double[] transf = geoFile[0].getTransform(); |
|
799 |
|
|
800 |
if(transf != null && (transf[2] != 0 || transf[4] != 0)){ |
|
801 |
|
|
802 |
//La transformaci?n se hace en base a una esquina que varia con el signo del |
|
803 |
//pixel size. |
|
804 |
double ptoDesplX = (transf[1] > 0)?requestExtent.minX():requestExtent.maxX(); |
|
805 |
double ptoDesplY = (transf[5] < 0)?requestExtent.maxY():requestExtent.minY(); |
|
806 |
|
|
807 |
Point2D ul = new Point2D.Double(vx - ptoDesplX, vy2 - ptoDesplY); |
|
808 |
Point2D ur = new Point2D.Double(vx2 - ptoDesplX, vy2 - ptoDesplY); |
|
809 |
Point2D ll = new Point2D.Double(vx - ptoDesplX, vy - ptoDesplY); |
|
810 |
Point2D lr = new Point2D.Double(vx2 - ptoDesplX, vy - ptoDesplY); |
|
811 |
|
|
812 |
double shearX = 0; |
|
813 |
double shearY = 0; |
|
814 |
if(transf[5] != 0) |
|
815 |
shearX = transf[2] / transf[5]; |
|
816 |
else |
|
817 |
shearX = transf[2]; |
|
818 |
if(transf[1] != 0) |
|
819 |
shearY = transf[4] / transf[1]; |
|
820 |
else |
|
821 |
shearY = transf[4]; |
|
822 |
|
|
823 |
AffineTransform at = new AffineTransform(); |
|
824 |
at.setToShear(shearX, shearY); |
|
825 |
|
|
826 |
try { |
|
827 |
at.inverseTransform(ul, ul); |
|
828 |
at.inverseTransform(ur, ur); |
|
829 |
at.inverseTransform(ll, ll); |
|
830 |
at.inverseTransform(lr, lr); |
|
831 |
} catch (NoninvertibleTransformException e) { |
|
832 |
e.printStackTrace(); |
|
833 |
} |
|
834 |
|
|
835 |
ul = new Point2D.Double(ul.getX() + ptoDesplX, ul.getY() + ptoDesplY); |
|
836 |
ur = new Point2D.Double(ur.getX() + ptoDesplX, ur.getY() + ptoDesplY); |
|
837 |
ll = new Point2D.Double(ll.getX() + ptoDesplX, ll.getY() + ptoDesplY); |
|
838 |
lr = new Point2D.Double(lr.getX() + ptoDesplX, lr.getY() + ptoDesplY); |
|
839 |
|
|
840 |
vx2 = Math.max(Math.max(ul.getX(), ur.getX()), Math.max(ll.getX(), lr.getX())); |
|
841 |
vy2 = Math.max(Math.max(ul.getY(), ur.getY()), Math.max(ll.getY(), lr.getY())); |
|
842 |
vx = Math.min(Math.min(ul.getX(), ur.getX()), Math.min(ll.getX(), lr.getX())); |
|
843 |
vy = Math.min(Math.min(ul.getY(), ur.getY()), Math.min(ll.getY(), lr.getY())); |
|
844 |
} |
|
845 |
} |
|
683 | 846 |
|
684 |
if (sz.minX() < extent.minX())
|
|
685 |
vx = extent.minX();
|
|
847 |
if (vx < requestExtent.minX())
|
|
848 |
vx = requestExtent.minX();
|
|
686 | 849 |
|
687 |
if (sz.minY() < extent.minY())
|
|
688 |
vy = extent.minY();
|
|
850 |
if (vy < requestExtent.minY())
|
|
851 |
vy = requestExtent.minY();
|
|
689 | 852 |
|
690 |
if (sz.maxX() > extent.maxX())
|
|
691 |
vx2 = extent.maxX();
|
|
853 |
if (vx2 > requestExtent.maxX())
|
|
854 |
vx2 = requestExtent.maxX();
|
|
692 | 855 |
|
693 |
if (sz.maxY() > extent.maxY())
|
|
694 |
vy2 = extent.maxY();
|
|
695 |
|
|
856 |
if (vy2 > requestExtent.maxY())
|
|
857 |
vy2 = requestExtent.maxY();
|
|
858 |
|
|
696 | 859 |
if (geoFile != null) { |
697 | 860 |
for (int i = 0; i < geoFile.length; i++) |
698 |
geoFile[i].setView(new Extent(vx, vy, vx2, vy2));
|
|
861 |
geoFile[i].setView(new Extent(vx, vy, vx2, vy2));
|
|
699 | 862 |
} else { |
700 | 863 |
System.err.println("PxRaster.calculateNewView(): Imagen no cargada."); |
701 | 864 |
} |
... | ... | |
729 | 892 |
} |
730 | 893 |
} |
731 | 894 |
|
732 |
/** |
|
733 |
* Dibuja el raster sobre el Graphics. Para ello debemos de pasar el viewPort que corresponde a la |
|
734 |
* vista. Este viewPort es ajustado a los tama?os m?ximos y m?nimos de la imagen por la funci?n |
|
735 |
* calculateNewView. Esta funci?n tambi?n asignar? la vista a los drivers. Posteriormente se calcula |
|
736 |
* el alto y ancho de la imagen a dibujar (wImg, hImg), as? como el punto donde se va a pintar dentro |
|
737 |
* del graphics (pt). Finalmente se llama a updateImage del driver para que pinte y una vez dibujado |
|
738 |
* se pasa a trav?s de la funci?n renderizeRaster que es la encargada de aplicar la pila de filtros |
|
739 |
* sobre el Image que ha devuelto el driver. |
|
740 |
* |
|
741 |
* @param g Graphics sobre el que se pinta |
|
742 |
* @param vp ViewPort de la extensi?n a dibujar |
|
743 |
*/ |
|
895 |
/** Dibuja el raster sobre el Graphics. Para ello debemos de pasar el viewPort que corresponde a la |
|
896 |
* vista. Este viewPort es ajustado a los tama?os m?ximos y m?nimos de la imagen por la funci?n |
|
897 |
* calculateNewView. Esta funci?n tambi?n asignar? la vista a los drivers. Posteriormente se calcula |
|
898 |
* el alto y ancho de la imagen a dibujar (wImg, hImg), as? como el punto donde se va a pintar dentro |
|
899 |
* del graphics (pt). Finalmente se llama a updateImage del driver para que pinte y una vez dibujado |
|
900 |
* se pasa a trav?s de la funci?n renderizeRaster que es la encargada de aplicar la pila de filtros |
|
901 |
* sobre el Image que ha devuelto el driver. |
|
902 |
* |
|
903 |
* Para calcular en que coordenada pixel (pt) se empezar? a pintar el BufferedImage con el raster le?do |
|
904 |
* se aplica sobre la esquina superior izquierda de esta la matriz de transformaci?n del ViewPortData |
|
905 |
* pasado vp.mat.transform(pt, pt). Si el raster no est? rotado este punto es el resultante de la |
|
906 |
* funci?n calculateNewView que devuelve la petici?n ajustada al extent de la imagen (sin rotar). Si |
|
907 |
* el raster est? rotado necesitaremos para la transformaci?n el resultado de la funci?n coordULRotateRaster. |
|
908 |
* Lo que hace esta ?ltima es colocar la petici?n que ha sido puesta en coordenadas de la imagen sin rotar |
|
909 |
* (para pedir al driver de forma correcta) otra vez en coordenadas de la imagen rotada (para calcular su |
|
910 |
* posici?n de dibujado). |
|
911 |
* |
|
912 |
* Para dibujar sobre el Graphics2D el raster rotado aplicaremos la matriz de transformaci?n con los |
|
913 |
* par?metros de Shear sobre este Graphics de forma inversa. Como hemos movido el fondo tendremos que |
|
914 |
* recalcular ahora el punto donde se comienza a dibujar aplicandole la transformaci?n sobre este |
|
915 |
* at.inverseTransform(pt, pt);. Finalmente volcamos el BufferedImage sobre el Graphics volviendo a dejar |
|
916 |
* el Graphics en su posici?n original al acabar. |
|
917 |
* |
|
918 |
* @param g Graphics sobre el que se pinta |
|
919 |
* @param vp ViewPort de la extensi?n a dibujar |
|
920 |
*/ |
|
744 | 921 |
public synchronized void draw(Graphics2D g, ViewPortData vp) { |
745 | 922 |
geoImage = null; |
746 |
|
|
923 |
double shearX = 0; |
|
924 |
double shearY = 0; |
|
925 |
double factor = 1; |
|
926 |
|
|
747 | 927 |
long t2; |
748 | 928 |
long t1 = new Date().getTime(); |
749 | 929 |
lastViewPort = vp; |
... | ... | |
755 | 935 |
return; |
756 | 936 |
} |
757 | 937 |
|
758 |
double[] adjustedExtent = calculateNewView(vp.getExtent()); |
|
759 |
|
|
938 |
double[] adjustedExtent = calculateNewView(vp); |
|
939 |
Point2D p2d = coordULRotateRaster(adjustedExtent); |
|
940 |
|
|
760 | 941 |
Extent v = geoFile[0].getView(); |
761 | 942 |
double x = v.minX(); |
762 | 943 |
double y = v.minY(); |
... | ... | |
770 | 951 |
int hImg = (int) Math.round(Math.abs(h * scaley));*/ |
771 | 952 |
int wImg = (int) Math.round(Math.abs((adjustedExtent[2] - adjustedExtent[0]) * scalex)); |
772 | 953 |
int hImg = (int) Math.round(Math.abs((adjustedExtent[3] - adjustedExtent[1]) * scaley)); |
773 |
|
|
954 |
|
|
774 | 955 |
if ((wImg <= 0) || (hImg <= 0)) |
775 | 956 |
return; |
776 |
|
|
957 |
|
|
777 | 958 |
//Para la transformaci?n usamos el extent que ha ajustado la funci?n calculateNewView y no usamos |
778 | 959 |
//el getView porque el getView puede haber sufrido una transformaci?n en caso de que exista |
779 | 960 |
//fichero .rmf. En caso de no existir este fichero ser?a lo mismo aplicar la funci?n: |
780 | 961 |
//Point2D.Double pt = new Point2D.Double(x, y + h); |
781 |
Point2D.Double pt = new Point2D.Double(adjustedExtent[0], adjustedExtent[3]); |
|
962 |
int wI = wImg, hI = hImg; |
|
963 |
double[] transf = bandSwitch.getBandR().getGeoRasterFile().getTransform(); |
|
964 |
Point2D.Double pt = null; |
|
965 |
if(transf != null && (transf[2] != 0 || transf[4] != 0)){ //Esta rotada |
|
966 |
pt = new Point2D.Double(p2d.getX(), p2d.getY()); |
|
967 |
wImg = (int) Math.round(Math.abs((adjustedRotedExtent[2] - adjustedRotedExtent[0]) * scalex)); |
|
968 |
hImg = (int) Math.round(Math.abs((adjustedRotedExtent[3] - adjustedRotedExtent[1]) * scaley)); |
|
969 |
}else{ //No est? rotada |
|
970 |
pt = new Point2D.Double(adjustedExtent[0], adjustedExtent[3]); |
|
971 |
} |
|
782 | 972 |
|
783 | 973 |
try { |
784 | 974 |
vp.mat.transform(pt, pt); |
... | ... | |
851 | 1041 |
|
852 | 1042 |
geoImage = renderizeRaster(geoImage, vp, v); |
853 | 1043 |
|
854 |
g.drawImage(geoImage, (int) (pt.getX()), (int) (pt.getY()), component); |
|
1044 |
AffineTransform at = new AffineTransform(); |
|
1045 |
|
|
1046 |
if(transf != null && (transf[2] != 0 || transf[4] != 0)){ |
|
1047 |
|
|
1048 |
//Obtenemos los par?metros de shearing |
|
1049 |
if(transf[5] != 0) |
|
1050 |
shearX = transf[2] / transf[5]; |
|
1051 |
else |
|
1052 |
shearX = transf[2]; |
|
1053 |
if(transf[1] != 0) |
|
1054 |
shearY = transf[4] / transf[1]; |
|
1055 |
else |
|
1056 |
shearY = transf[4]; |
|
1057 |
|
|
1058 |
//Aplicamos el shear a la vista |
|
1059 |
at.setToShear(-shearX, -shearY); |
|
1060 |
|
|
1061 |
//Escalamos en pixeles la misma cantidad que hemos le?do de m?s. |
|
1062 |
at.scale(((double)wI/(double)wImg), ((double)hI/(double)hImg)); |
|
1063 |
|
|
1064 |
g.transform(at); |
|
1065 |
|
|
1066 |
//Aplicamos el shear inverso al punto donde se comienza a dibujar |
|
1067 |
at.inverseTransform(pt, pt); |
|
1068 |
|
|
1069 |
g.drawImage(geoImage, (int) (pt.getX()), (int) (pt.getY()), component); |
|
1070 |
g.transform(at.createInverse()); |
|
1071 |
}else |
|
1072 |
g.drawImage(geoImage, (int) (pt.getX()), (int) (pt.getY()), component); |
|
1073 |
|
|
1074 |
|
|
855 | 1075 |
} else { // no cargada |
856 | 1076 |
System.err.println("Dibujando PxRaster: Foto no cargada."); |
857 | 1077 |
} |
Also available in: Unified diff