[Java-collab] geometry factory vs interface

Jorge Piera jorge.piera at iver.es
Thu Aug 13 02:01:22 EDT 2009


Jody Garnett wrote:
>> I think that one of the main goals of this project has to be to define
>> an API for geometries and the usage of Interfaces is normally more
>> flexible that the usage of abstract classes. I always prefer to define a
>> Interface and a default implementation for this Interface.
>>
>> In the proposal of interfaces that Markus did I've seen methods like:
>>
>> - public boolean isBeyond( Geometry geometry, Measure distance );
>> - public boolean isWithin( Geometry geometry );
>> - public boolean overlaps( Geometry geometry );
>> - ...
>>
>> that are not refered to the geometry structure. They are operations! We
>> have to separate structure of functionality and I suggest that all these
>> methods have not to be here.
>>
>> In gvSIG we have replaced all these methods by just one:
>>
>> - public Object invokeOperation(int index, GeometryOperationContext ctx)
>>
>> Details can be found here [1]. Yes, we know that we are losing
>> performance with this option but we are winning in other issues:
>
> I like it Jorge - now you are playing with fire :-)
>
> I would actually like a compromise for usability here ... I would like 
> something like the following (don't pick on the example too much since 
> I am thinking as I type :D ).
>
> /**
>  * Test if we are a set distance beyond another geometry.
>  * <p>
>  * This is a connivence method for the following call:<pre><code>
>  * return invokeOperation( BeyondOperationContext( this, geom, 
> distance ));</code></pre>
>  * <p>
>  * @geom Geometry to check against; care should be taken that it is in 
> the same CRS
> * @geom distance distance to check from geom
>  * @returns true if distance beyond the indicated geom.
>  */
> public boolean isBeyond( Geometry geom, Measure distance );
> /**
> public boolean invokeOperation(  BooleanOperationContext );
>
> public Geometry union( Geometry geom );
> public Geometry invokeOperation( GeometryOperationContext );
>
> Indeed I would rather *not* have the "invokeOperation" as part of the 
> Geometry; since I expect to have a switch board of operations to 
> choose from based on the geometry involved; CRS being used and so on.
>
> Jorge are you familiar with the operation split in JTS? The recent 
> operation for  PrepairedGeometry construct? It is used to hold onto 
> intermediate results (edge graphs and so on).  This is what I envision 
> for a GeometryOperationContext ...
No, I'm not familiar but I'm going to have a look.
>> - The Geometry Interface is always the same (we don't have the problem
>> that has been commented above).
>> - Using this system is possible to provide a new implementation of one
>> concrete operation associated to a GeometryType and it is not necessary
>> to update the GeometryType (separation between structure and 
>> functionality).
>>>> Especially, for Point and Envelope I would also like to have 
>>>> constructors alternatively to a factory:
>>>>
>>>> Point p = new Point (0,1);
>>>>
>>>> is just nicer to write than
>>>>
>>>> GeometryFactory.getInstance().createPoint (0,1);
>>>
>>> You have highlighted one place where I was sure I would need an 
>>> interface :-) Indeed when a Points data structure provides access to 
>>> a single Point it often would use a light weight implementation of 
>>> Point that would delegate onto the backing double[] for example. Or 
>>> another implementation could make use of a List<PointImpl> etc... I 
>>> see later in this email you talk about recycling a Point object when 
>>> iterating; to accomplish this you will need to define Point as a 
>>> data object and add equals and hashcode to the interface.
>> Point has to be always an Interface. We can have the classes Point2D,
>> Point3D.... and we can not make a "new" of any of them. We can maybe use
>> the Builder pattern to provide different sets of geometries.
>>
>> In gvSIG it is possible to add your own implementation of GeometryType
>> separately and we have a "GeometryManager" to create them:
>>
>> Point point = geometryManager.createPoint(2);
>>
>> 2 is the dimension of the geometry. We have a faster way to create a
>> point in 2 dimensions using the method:
>>
>> Point point = geometryManager.createPoint(0,1, 2);
>>
>> It works because a "point in 2 dimensions" has been previously
>> registered on our manager and everyone can register its own
>> implementation of a Point2D.
>
> Interesting; we have selection of geometry factory implementations. 
> And a GeometryBuilder that will hunt down the correct factory for the 
> CRS you are building against (so we don;t say 2 - we let that part 
> come from the CRS definition). In anycase that is neither here nor 
> there .. we have come up with a similar design.
It looks an interesting approach the usage of the CRS. But there is a 
small detail that I hid in my last email to simplify the example. Really 
we don't use "2" to define the dimension. We use a set on constants in 
our application to classify our geometries:

- GEOM2D
- GEOM2DZ
- GEOM2M
- GEOM3D
- GEOM3DM

"M" means the "M coordinate". In a future we also can add geometries 
with Time or other classes of geometries. If you only uses the CRS is 
not possible to specify if you want a geometry with support for the M 
coordinate.

>
> One thing I found *bad* about this design in geotools is that we had 
> too many small factories; indeed a GeometryBuilder was kind of needed 
> since it was a pain to hunt down the correct AggregateFactory, 
> PositionFactory, PrecisionFactory, ComplexFactory and GeometryFactory :-)
>
> So some kind of balance would be good; I imagine this is something we 
> can sort out with live code examples when the time comes?
>
> Just to bury my original point:
> - we *could* make use of classes for Geometry; as long as we have the 
> invokeOperation stuff isolated behind interfaces.
> - it is probably only useful as an extreme to force us to think about 
> what we are doing
> - please consider the geotools implementation of many little factories 
> as the other extreme
>
> With that in mind Jorge - how are you actually getting along with your 
> approach? Is there anything that "boiler plate" or hard to do? I could 
> see making a bunch of calls to register stuff with your 
> geometryManager - and just cutting and pasting that code against and 
> again; just so I did not have to *think* when creating points.
I suppose that with Geotools I can register my own set of factories to 
create my own geometries. Cool! The difference is that we can register 
single geometries: e.g: I can register my own implementation for a Point 
with 2 dimensions, and I only have to register the class that implements it.

It is true that you have to do a bunch of calls to register all the 
geometries in the GeometryManager, but I think that it is not any 
problem: this code is written just one time and in the 99% of the times 
is not necessary to update it. Only if you want to add your own geometry 
you have to register it.

It is just other approach.

Best regards,
Jorge.

-- 
Jorge Piera Llodrá
Especialista en Servicios OGC
Equipo de desarrollo gvSIG
IVER TI S.A.
C/ Lérida, 20
46009-Valencia (Spain)
Tlf.+34902252540
www.iver.es
www.gvsig.com  



More information about the Java-collab mailing list