El 1 de junio de 2017, 20:09, Alex Irmel Oviedo Solis < [email protected]> escribió:
> Buenas tardes, continuo modificando la extension LandRegistryViewer y > necesito obtener registros asociados a un poligono pero de la forma actual > de la extension se muestran más resultados de los que deberian y no > entiendo del todo el codigo para modificar ese comportamiento. > > Por lo poco que entiendo, la clase IntersectsEvaluator que extiende a > AbstractEvaluator es la que realiza la consulta de intersección de un punto > con los poligonos y que al parecer tiene un buffer alto y por esto > intersecta a más de un poligono y lo que requiero es que el buffer sea > minimo para obtener un solo poligono. > > Espero que me puedan dar una ayudita en este problema, gracias de > antemano. Saludos > > _______________________________________________ > gvSIG_desarrolladores mailing list > [email protected] > Para ver histórico de mensajes, editar sus preferencias de usuario o darse > de baja en esta lista, acuda a la siguiente dirección: > https://listserv.gva.es/cgi-bin/mailman/listinfo/gvsig_desarrolladores > > Hola Alex, no entiendo cual es tu problema, te voy contando a ver si te sirve algo de lo que te cuento y con todo ya ves de concretar un poco mas la duda. La forma de recuperar registros de una fuente de datos seria algo como: FeatureStore store = ... ; FeatureSet set = null; DisposableIterator it = null; try { set = store.getFeatureStore(); it = set.fastIterator(); while( it.hasNext() ) { Feature f = (Feature) it.next(); ... hacer lo que toque con la feature ... } } catch(Throwable th) { ... tratamiento de errores ... } finally { DisposeUtils.disposeQuietly(it); DisposeUtils.disposeQuietly(set); } Cuando sea posible recomiendo usar un visitor en lugar de iterar sobre los registros pero entiendo que sea mas facil entender la version con el iterador. De todos modos dejo aqui la version del visitor. FeatureStore store = ... ; FeatureSet set = null; DisposableIterator it = null; try { set = store.getFeatureStore(); set.accept(new Visitor() { public void visit(Object obj) throws VisitCanceledException, BaseException { Feature f = (Feature) obj; ... hacer lo que toque con la feature ... } ); } catch(Throwable th) { ... tratamiento de errores ... } finally { DisposeUtils.disposeQuietly(set); } Bueno, elejimos una u otra forma para recorrer las features de una fuente de datos. Ahora bien asi, nos recorremos todas las features de esa fuente de datos. ¿ Y si solo queremos unas pocas ? Si solo queremos las features cuya geometria intersecte con un poligono dado. Invocaremos al metodo getFeatureStore, pero pasandole la condicion de filtrado que deseemos. Vamos a ver como hacerlo. FeatureQuery query = store.createFeatureQuery(); Evaluator filtro = MyIntersectsEvaluator(...); query.setFilter(filtro); set = store.getFeatureStore(query); De esta forma obtendriamos las features que cumplen el filtro especificado. ¿ Y que es ese filtro ? El filtro es una instancia de Evaluator. Simplificando la explicacion, la libreria de acceso a datos lo que hace es, recoger todas las features y para cada una de ellas invoca al metodo evaluate del filtro. Si este metodo devuelbe true, esa feature es incluida en el resultado de la consulta, si no, no es incluida. El metodo evaluate recive los datos de la feature para que puedas realizar con ellos la operacion que necesites. Vamos a ver un ejemplo. El de interseccion con un punto. El metodo evaluate podria ser algo como: public Object evaluate(EvaluatorData data) throws EvaluatorException { Geometry geom = (Geometry) data.getDataValue("the_geom"); try { return punto.intersects(geom); } catch (GeometryOperationNotSupportedException e) { throw new EvaluatorException(e); } catch (GeometryOperationException e) { throw new EvaluatorException(e); } } para cada feature de nuestra fuente de datos se llamara a este evaluate. En data recibiremos los datos de la feature. Asumo que la geometria esta en el campo "the_geom", asi que lo primero es recuperar la geometria. Luego, simplemente compruebo si intersecta con mi punto y devuelbo el resultado (si intersecta o no). La clase MyIntersectsEvaluator podia quedar algo como: public class MyIntersectsEvaluator extends AbstractEvaluator { private Geometry punto; public MyIntersectsEvaluator(Geometry punto) throws GeometryOperationNotSupportedException, GeometryOperationException { this.punto = punto; } public String getName() { return "IntersectaConPunto"; } public Object evaluate(EvaluatorData data) throws EvaluatorException { Geometry geom = (Geometry) data.getDataValue("the_geom"); try { return punto.intersects(geom); } catch (GeometryOperationNotSupportedException e) { throw new EvaluatorException(e); } catch (GeometryOperationException e) { throw new EvaluatorException(e); } } } Si creamos uno de estos y lo aplicamos al query como un filtro, el set solo nos devolbera las features que intersecten con nuestro poligono. Si lo dejamos asi funcionara, y con un shape, o un dxf, ira bien; pero con una BBDD ira muy lento. Esto es por que la libreria de acceso a datos, se traera todas las filas de la tabla y comprobara una a una si cumplen el criterio indicado. Podemos optimizar esto añadiendo el metodo getCQL a nuestra clase con algo como: public String getCQL() { where = MessageFormat.format( " intersects(the_geom, GeomFromText('{1}','{2}')) ", new Object[] { punto.convertToWKT(), proj.getAbbrev() } ); return where; } Y añadiremos en el constructo la rojeccion en la que se encuentra el poligono: public MyIntersectsEvaluator(Geometry punto, IProjection proj) throws GeometryOperationNotSupportedException, GeometryOperationException { this.punto = punto; this.proj = proj; } ¿ Que es lo que conseguimos con esto ? Si aplicamos este filtro a un shape, nada. El resultado sera el mismo que antes. Sim embargo, si lo aplicamos a un tabla de PostgreSQL tendremos unas mejoras sustanciales en el rendimiento. El proveedor de datos de PostgreSQL de gvSIG, ve que el metodo getCQL devuelbe una cadena, y la añade al where de la sentencia SQL que va a usar para recuperar los datos. Asi que la BBDD solo devolvera los datos que cumplan el criterio que hemos indicado en esa funcion. Luego, la libreria de acceso a datos volvera a aplicar el filtro de nuestro evaluador a cada una de las features recuperadas, pero ya no sera a todas las de la tabla, si no solo a las que hayamos restringido con lo que devuelba el getCQL. Es muy importante que la proyeccion del punto y la de las geometrias de la tabla de la BBDD sean la misma, si no los resultados pueden ser algo impredecibles. Con gvSIG 2.3.3 y 2.4 se han añadido mejoras que permiten independizar como construimos lo que devuelbe el getCQL de la BBDD que se esta usando para que asi nuestra consulta funcione con todas las BBDD que soporte gvSIG, pero de momento voy a dejarlo asi. Tambien podriamos pasarle a muestra clase MyIntersectsEvaluator como se llama la columna geometria con la que queremos comparar nuestro punto (por si no se llama "the_geom"). Asi nuestra clase seria independiente de ese valor. Sobre lo del buffer que comentas... en la clase IntersectsEvaluator que hay en la implementacion de langregistryviewer no he visto que se haga ningun buffer, ni tampoco antes de pasarle el punto sobre el que se realiza la interseccion. ¿ Podria ser que tuvieses en la fuente de datos geometrias que se superponen ? Bueno, lo dejo aqui y ya vas preguntando cosas mas concretas. Por cierto, el codigo lo he picado directamente aqui, podria haberme confundido en el nombre de algun identificador, espero que no. Un saludo Joaquin -- -------------------------------------- Joaquin Jose del Cerro Murciano Development and software arquitecture manager at gvSIG Team [email protected] [email protected] gvSIG Association www.gvsig.com www.gvsig.org
_______________________________________________ gvSIG_desarrolladores mailing list [email protected] Para ver histórico de mensajes, editar sus preferencias de usuario o darse de baja en esta lista, acuda a la siguiente dirección: https://listserv.gva.es/cgi-bin/mailman/listinfo/gvsig_desarrolladores
