[Geoserver-devel] "No factory of kind" error when creating a WKTParser

Following a suggestion from Andrea of some months ago, I started adding the possibility of having marks defined as WKT.... but, while adding this behaviour to the ShapeMarkFactory class, I've found out that the following code:

WKTParser parser= new WKTParser(new GeometryBuilder(DefaultGeographicCRS.WGS84));

raises this exception:
2010-04-26 16:18:23,542 DEBUG [org.geotools.rendering] - Exception while scanning for the appropriate mark factory
org.geotools.factory.FactoryNotFoundException: No factory of kind "GeometryFactory" found.
         at org.geotools.factory.FactoryRegistry.getServiceProvider(FactoryRegistry.java:374)
         at org.geotools.factory.FactoryCreator.getServiceProvider(FactoryCreator.java:143)
         at org.geotools.geometry.GeometryFactoryFinder.getGeometryFactory(GeometryFactoryFinder.java:92)
         at org.geotools.geometry.GeometryBuilder.getGeometryFactory(GeometryBuilder.java:213)
         at org.geotools.geometry.text.WKTParser.<init>(WKTParser.java:108)

Any clue ?

--------------------
    Luca Morandini
www.lucamorandini.it
--------------------

Luca Morandini ha scritto:

Following a suggestion from Andrea of some months ago, I started adding the possibility of having marks defined as WKT.... but, while adding this behaviour to the ShapeMarkFactory class, I've found out that the following code:

WKTParser parser= new WKTParser(new GeometryBuilder(DefaultGeographicCRS.WGS84));

raises this exception:
2010-04-26 16:18:23,542 DEBUG [org.geotools.rendering] - Exception while scanning for the appropriate mark factory
org.geotools.factory.FactoryNotFoundException: No factory of kind "GeometryFactory" found.
         at org.geotools.factory.FactoryRegistry.getServiceProvider(FactoryRegistry.java:374)
         at org.geotools.factory.FactoryCreator.getServiceProvider(FactoryCreator.java:143)
         at org.geotools.geometry.GeometryFactoryFinder.getGeometryFactory(GeometryFactoryFinder.java:92)
         at org.geotools.geometry.GeometryBuilder.getGeometryFactory(GeometryBuilder.java:213)
         at org.geotools.geometry.text.WKTParser.<init>(WKTParser.java:108)

Any clue ?

Which WKTParser are you using?
Try to stick with the JTS one, you may be using the geotools one which is the result of an unfinished experiment by Jody and Mark to add support for curves

Cheers
Andrea

--
Andrea Aime
OpenGeo - http://opengeo.org
Expert service straight from the developers.

Luca Morandini ha scritto:

Following a suggestion from Andrea of some months ago, I started adding the possibility of having marks defined as WKT

Oh, btw, did you look into the issue of how does one build a WKT marker that way? Like, where to find a visual editor to generate WKT?
Remember the thing that WKT is easy to parse, but we lack and editor,
whilst for SVG with have open source editors, but we'd need to strip
off all the styling and build AWT shapes out of the SVG geometries?

Just curious if you looked into the question at all. A WKT based mark
factory is fine by me :wink:

Cheers
Andrea

--
Andrea Aime
OpenGeo - http://opengeo.org
Expert service straight from the developers.

On 26/04/10 19:09, Andrea Aime wrote:

Luca Morandini ha scritto:

Following a suggestion from Andrea of some months ago, I started adding the
possibility of having marks defined as WKT

Oh, btw, did you look into the issue of how does one build a WKT marker
that way? Like, where to find a visual editor to generate WKT?

Negative, I did not... though I do not rule the possibility :wink:

--------------------
    Luca Morandini
www.lucamorandini.it
--------------------

On 26/04/10 19:57, Luca Morandini wrote:

On 26/04/10 19:09, Andrea Aime wrote:

Luca Morandini ha scritto:

Following a suggestion from Andrea of some months ago, I started adding the
possibility of having marks defined as WKT

Oh, btw, did you look into the issue of how does one build a WKT marker
that way? Like, where to find a visual editor to generate WKT?

Negative, I did not... though I do not rule the possibility :wink:

Ouch... I meant "I do not rule OUT the possibility"

--------------------
    Luca Morandini
www.lucamorandini.it
--------------------

On 26/04/10 19:09, Andrea Aime wrote:

Just curious if you looked into the question at all. A WKT based mark
factory is fine by me :wink:

That I did, including some tests (patches at the end of this message); of course, some user doc will have to be written too. By the way, the source code includes some more well-known shapes that I've found useful.

As per SVG, I've found out some "orphan" code that may be of interest (http://www.mail-archive.com/batik-users@anonymised.com/msg04729.html).

If you deem it worthy, I may try to adapt it to GeoTools.

Regards,

--------------------
    Luca Morandini
www.lucamorandini.it
--------------------

### Eclipse Workspace Patch 1.0
#P geotools-2.6.x
Index: modules/library/render/src/main/java/org/geotools/renderer/style/ShapeMarkFactory.java

--- modules/library/render/src/main/java/org/geotools/renderer/style/ShapeMarkFactory.java (revision 35265)
+++ modules/library/render/src/main/java/org/geotools/renderer/style/ShapeMarkFactory.java (working copy)
@@ -27,12 +27,16 @@
  import java.util.logging.Logger;

  import org.geotools.renderer.style.shape.ExplicitBoundsShape;
+
+import org.geotools.geometry.jts.LiteShape;
+import org.geotools.geometry.jts.WKTReader2;
  import org.opengis.feature.Feature;
  import org.opengis.filter.expression.Expression;

  public class ShapeMarkFactory implements MarkFactory {

      private static final String SHAPE_PREFIX = "shape://";
+ private static final String WKT_PREFIX = "wkt://";

      /** The logger for the rendering module. */
      private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger(
@@ -63,20 +67,74 @@
         gp.moveTo(-0.5f, -0.5f);
         gp.lineTo(0.5f, 0.5f);
         shapes.put("times", gp);
+
+ gp = new GeneralPath();
+ gp.moveTo(-0.5f, -0.125f);
+ gp.lineTo(-0.125f, -0.125f);
+ gp.lineTo(0.0f, 0.125f);
+ gp.lineTo(0.125f, -0.125f);
+ gp.lineTo(0.5f, -0.125f);
+ gp.closePath();
+ shapes.put("triangle", gp);
+
+ gp = new GeneralPath();
+ gp.moveTo(-0.5f, -0.125f);
+ gp.lineTo(-0.125f, -0.125f);
+
+ for (float i=8.0f; i >= 0.0f; i=i -1.0f ) {
+ gp.lineTo(
+ (float)(0.0f + Math.cos(Math.PI * i / 8.0f) * 0.25f),
+ (float)(-0.125f + Math.sin(Math.PI * i / 8.0f) * 0.25f)
+ );
+ }
+
+ gp.lineTo(0.5f, -0.125f);
+ gp.closePath();
+ shapes.put("semicircle", gp);
+
+ gp = new GeneralPath();
+ gp.moveTo(-0.5f, -0.125f);
+ gp.lineTo(-0.375f, -0.125f);
+
+ for (float i=8.0f; i >= 0.0f; i=i -1.0f ) {
+ gp.lineTo(
+ (float)(-0.25f + Math.cos(Math.PI * i / 8.0f) * 0.125f),
+ (float)(-0.125f + Math.sin(Math.PI * i / 8.0f) * 0.125f)
+ );
+ }
+
+ gp.lineTo(0.125f, -0.125f);
+ gp.lineTo(0.25f, -0.375f);
+ gp.lineTo(0.375f, -0.125f);
+ gp.lineTo(0.5f, -0.125f);
+ gp.closePath();
+ shapes.put("trianglesemicircle", gp);
      }

      public Shape getShape(Graphics2D graphics, Expression symbolUrl, Feature feature) throws Exception {
+
          // cannot handle a null url
- if(symbolUrl == null)
+ if(symbolUrl == null) {
              return null;
+ }

- // see if it's a shape://
- String wellKnownName = symbolUrl.evaluate(feature, String.class);
- if(!wellKnownName.startsWith(SHAPE_PREFIX))
- return null;
+ // see if it's a shape
+ String wellKnown = symbolUrl.evaluate(feature, String.class);
+ if ( wellKnown.startsWith(SHAPE_PREFIX)) {

- String name = wellKnownName.substring(SHAPE_PREFIX.length());
- return shapes.get(name);
+ String wellKnownName = wellKnown.substring(SHAPE_PREFIX.length());
+ return shapes.get(wellKnownName);
+ }
+
+ // Otherwise, See if it is a WKT
+ if ( wellKnown.startsWith(WKT_PREFIX)) {
+ String wellKnownText = wellKnown.substring(WKT_PREFIX.length());
+ WKTReader2 reader= new WKTReader2();
+ LiteShape shape= new LiteShape(reader.read(wellKnownText), null, false);
+ return shape;
+ }
+
+ return null;
      }

-}
+}
\ No newline at end of file

### Eclipse Workspace Patch 1.0
#P geotools-2.6.x
Index: modules/library/render/src/test/java/org/geotools/renderer/style/ShapeMarkFactoryTest.java

--- modules/library/render/src/test/java/org/geotools/renderer/style/ShapeMarkFactoryTest.java (revision 0)
+++ modules/library/render/src/test/java/org/geotools/renderer/style/ShapeMarkFactoryTest.java (revision 0)
@@ -0,0 +1,148 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ */
+
+package org.geotools.renderer.style;
+
+import org.opengis.feature.simple.SimpleFeature;
+import org.opengis.feature.simple.SimpleFeatureType;
+import org.opengis.filter.expression.Expression;
+import org.geotools.factory.CommonFactoryFinder;
+import org.geotools.feature.simple.SimpleFeatureBuilder;
+import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
+import org.opengis.filter.FilterFactory;
+import org.geotools.referencing.crs.DefaultGeographicCRS;
+
+import com.vividsolutions.jts.geom.LineString;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for shape mark factory
+ *
+ * @author Luca Morandini lmorandini@anonymised.com
+ *
+ * @source $URL:$
+ */
+public class ShapeMarkFactoryTest extends TestCase {
+
+ private SimpleFeature feature;
+ private Expression exp;
+ private FilterFactory ff;
+
+ {
+ try {
+ ff = CommonFactoryFinder.getFilterFactory(null);
+ SimpleFeatureTypeBuilder featureTypeBuilder = new SimpleFeatureTypeBuilder();
+ featureTypeBuilder.setName("TestType");
+ featureTypeBuilder.add("geom", LineString.class,
+ DefaultGeographicCRS.WGS84);
+ SimpleFeatureType featureType = featureTypeBuilder
+ .buildFeatureType();
+ SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(
+ featureType);
+ this.feature = featureBuilder.buildFeature(null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void testWellKnownName() {
+ ShapeMarkFactory smf = new ShapeMarkFactory();
+ try {
+ this.exp = ff.literal("shape://plus");
+ smf.getShape(null, this.exp, this.feature);
+ } catch (Exception e) {
+ assertTrue(false);
+ return;
+ }
+
+ assertTrue(true);
+ }
+
+ public void testWellKnownTextLineString() {
+ ShapeMarkFactory smf = new ShapeMarkFactory();
+ try {
+ this.exp = ff
+ .literal("wkt://LINESTRING(0.0 0.25, 0.25 0.25, 0.5 0.75, 0.75 0.25, 1.00 0.25)");
+ smf.getShape(null, this.exp, this.feature);
+ } catch (Exception e) {
+ assertTrue(false);
+ return;
+ }
+
+ assertTrue(true);
+ }
+
+ public void testWellKnownTextMultiLineString() {
+ ShapeMarkFactory smf = new ShapeMarkFactory();
+ try {
+ this.exp = ff
+ .literal("wkt://MULTILINESTRING((0.25 0.25, 0.5 0.75, 0.75 0.25, 0.25 0.25), (0.25 0.75, 0.5 0.25, 0.75 0.75, 0.25 0.75))");
+ smf.getShape(null, this.exp, this.feature);
+ } catch (Exception e) {
+ assertTrue(false);
+ return;
+ }
+
+ assertTrue(true);
+ }
+
+ public void testWellKnownTextPolygon() {
+ ShapeMarkFactory smf = new ShapeMarkFactory();
+ try {
+ this.exp = ff
+ .literal("wkt://POLYGON((0.25 0.25, 0.5 0.75, 0.75 0.25, 0.25 0.25))");
+ smf.getShape(null, this.exp, this.feature);
+ } catch (Exception e) {
+ assertTrue(false);
+ return;
+ }
+
+ assertTrue(true);
+ }
+
+ public void testWellKnownTextPolygonError() {
+ ShapeMarkFactory smf = new ShapeMarkFactory();
+ try {
+ this.exp = ff
+ .literal("wkt://POLYGON((0.25 0.25, 0.5 0.75, 0.75 0.25, ))");
+ smf.getShape(null, this.exp, this.feature);
+ } catch (Exception e) {
+ assertTrue(true);
+ return;
+ }
+
+ assertTrue(false);
+ }
+
+ public void testUnknownProtocol() {
+ ShapeMarkFactory smf = new ShapeMarkFactory();
+ try {
+ this.exp = ff
+ .literal("xxx://POLYGON((0.25 0.25, 0.5 0.75, 0.75 0.25,))");
+ if (smf.getShape(null, this.exp, this.feature) == null) {
+ assertTrue(true);
+ return;
+ }
+ } catch (Exception e) {
+ assertTrue(false);
+ return;
+ }
+
+ assertTrue(false);
+ }
+}

Property changes on: modules/library/render/src/test/java/org/geotools/renderer/style/ShapeMarkFactoryTest.java
___________________________________________________________________
Added: svn:keywords
    + Id

Luca Morandini ha scritto:

On 26/04/10 19:09, Andrea Aime wrote:

Just curious if you looked into the question at all. A WKT based mark
factory is fine by me :wink:

That I did, including some tests (patches at the end of this message); of course, some user doc will have to be written too. By the way, the source code includes some more well-known shapes that I've found useful.

Ah, thanks for the patch. Can you attach it to a jira in Geotools?
Here on the ml I'll probably forget about it before I have time to
merge it with GeoTools.

Btw, I did not think about using a WKT literal, but yeah, it's a simple solution (I was thinking more or a property file, but in that case you
also have to make the property file location pluggable and so on, which
might be annoying).

As per SVG, I've found out some "orphan" code that may be of interest (http://www.mail-archive.com/batik-users@anonymised.com/msg04729.html).

If you deem it worthy, I may try to adapt it to GeoTools.

Sounds interesting, but also seems to duplicate part of Batik work.
This suggestion:
http://www.mail-archive.com/batik-users@anonymised.com/msg04718.html

seems to have more potential. Batik already has to turn the elements
into shapes to paint them on Java2D, so a fake Graphics2D could be
used to extract the generated shape if no other way is available
(see the discussion about the ShapeNode class)

Cheers
Andrea

--
Andrea Aime
OpenGeo - http://opengeo.org
Expert service straight from the developers.

On 27/04/10 18:54, Andrea Aime wrote:

Luca Morandini ha scritto:

On 26/04/10 19:09, Andrea Aime wrote:

Just curious if you looked into the question at all. A WKT based mark
factory is fine by me :wink:

That I did, including some tests (patches at the end of this message); of course,
some user doc will have to be written too. By the way, the source code includes
some more well-known shapes that I've found useful.

Ah, thanks for the patch. Can you attach it to a jira in Geotools?

Done (http://jira.codehaus.org/browse/GEOT-3058).

Btw, I did not think about using a WKT literal, but yeah, it's a simple
solution (I was thinking more or a property file, but in that case you
also have to make the property file location pluggable and so on, which
might be annoying).

My first idea was indeed to use an URL to fetch the WKT file, but the option of having the WKT in-lined makes the SLD self-contained and the whole process easier for the user... on the other hand, it might be useful to have an external "library" of WKTs to re-use.

As per SVG, I've found out some "orphan" code that may be of interest
(http://www.mail-archive.com/batik-users@anonymised.com/msg04729.html).

If you deem it worthy, I may try to adapt it to GeoTools.

Sounds interesting, but also seems to duplicate part of Batik work.
This suggestion:
http://www.mail-archive.com/batik-users@anonymised.com/msg04718.html

I've considered Batik too... but that piece of code (the "orphan" one) does exactly what's needed, doesn't it ?

Anyway, the links you quoted is broken... but I've found out some code, on batik-users, under the thread named "Roundtrip Java2D Shape -> SVG File -> Java2D Shape": is this the one you are referring to ?

Regards,

--------------------
    Luca Morandini
www.lucamorandini.it
--------------------

Luca Morandini ha scritto:

On 27/04/10 18:54, Andrea Aime wrote:

Luca Morandini ha scritto:

On 26/04/10 19:09, Andrea Aime wrote:

Just curious if you looked into the question at all. A WKT based mark
factory is fine by me :wink:

That I did, including some tests (patches at the end of this message); of course,
some user doc will have to be written too. By the way, the source code includes
some more well-known shapes that I've found useful.

Ah, thanks for the patch. Can you attach it to a jira in Geotools?

Done (http://jira.codehaus.org/browse/GEOT-3058).

Btw, I did not think about using a WKT literal, but yeah, it's a simple
solution (I was thinking more or a property file, but in that case you
also have to make the property file location pluggable and so on, which
might be annoying).

My first idea was indeed to use an URL to fetch the WKT file, but the option of having the WKT in-lined makes the SLD self-contained and the whole process easier for the user... on the other hand, it might be useful to have an external "library" of WKTs to re-use.

Right, was thinking the same.
Looking at your patch I was thinking of doing the following:
- keeping the well known extra shapes in the shape factory
- make a new wkt factory that only does wkt
- have it recognize a wktlib:// prefix too that points to a file,
   something like "wktlib://path#name"
   Possibly so that the path can be a relative reference into the
   GeoServer data dir, would be nice to have wktlib://mylib#star
   where the data dir contains $data_dir/styles/mylib.properties.
   Should be doable by allowing for pluggable path resolvers
   of some kind... or to make it easier, just do the abstract class
   in GeoTools and then make a subclass in GeoServer that has the
   lookup logic.

What do you think?

As per SVG, I've found out some "orphan" code that may be of interest
(http://www.mail-archive.com/batik-users@anonymised.com/msg04729.html).

If you deem it worthy, I may try to adapt it to GeoTools.

Sounds interesting, but also seems to duplicate part of Batik work.
This suggestion:
http://www.mail-archive.com/batik-users@anonymised.com/msg04718.html

I've considered Batik too... but that piece of code (the "orphan" one) does exactly what's needed, doesn't it ?

Anyway, the links you quoted is broken... but I've found out some code, on batik-users, under the thread named "Roundtrip Java2D Shape -> SVG File -> Java2D Shape": is this the one you are referring to ?

Err... no, I was just refererring to an idea, which is to let Batik
draw to a Graphics (which it can do) and have a special Graphics implementation that steals the Shape objects passed down to it

Cheers
Andrea

--
Andrea Aime
OpenGeo - http://opengeo.org
Expert service straight from the developers.

On 28/04/10 08:38, Andrea Aime wrote:

Luca Morandini ha scritto:

My first idea was indeed to use an URL to fetch the WKT file, but the option of
having the WKT in-lined makes the SLD self-contained and the whole process easier
for the user... on the other hand, it might be useful to have an external
"library" of WKTs to re-use.

Right, was thinking the same.
Looking at your patch I was thinking of doing the following:
- keeping the well known extra shapes in the shape factory

Thanks: I need them... especially the semicircle, which would be annoying to replicate in a WKT.

- make a new wkt factory that only does wkt

Makes sense.

- have it recognize a wktlib:// prefix too that points to a file,
    something like "wktlib://path#name"
    Possibly so that the path can be a relative reference into the
    GeoServer data dir, would be nice to have wktlib://mylib#star
    where the data dir contains $data_dir/styles/mylib.properties.
    Should be doable by allowing for pluggable path resolvers
    of some kind... or to make it easier, just do the abstract class
    in GeoTools and then make a subclass in GeoServer that has the
    lookup logic.

Do you mean a property file like:
star=LINESTRING(10 20, 20 20, ...)
square=POLYGON((10 10, ...))

?

What do you think?

Well, while I clearly see the need for SVG, the implementation of this library looks to me like overstretching the requirement a bit... but it would be a rather elegant solution :slight_smile:

I've considered Batik too... but that piece of code (the "orphan" one) does
exactly what's needed, doesn't it ?

Err... no, I was just refererring to an idea, which is to let Batik
draw to a Graphics (which it can do) and have a special Graphics
implementation that steals the Shape objects passed down to it

Never programmed Batik, I will have to study it first.

One question: shall WKT and SVG be confined in a coordinate space of (-0.5 -0.5, 0.5 0.5) for the GraphicMark to work ?

Regards,

--------------------
    Luca Morandini
www.lucamorandini.it
--------------------

Luca Morandini ha scritto:

- have it recognize a wktlib:// prefix too that points to a file,
    something like "wktlib://path#name"
    Possibly so that the path can be a relative reference into the
    GeoServer data dir, would be nice to have wktlib://mylib#star
    where the data dir contains $data_dir/styles/mylib.properties.
    Should be doable by allowing for pluggable path resolvers
    of some kind... or to make it easier, just do the abstract class
    in GeoTools and then make a subclass in GeoServer that has the
    lookup logic.

Do you mean a property file like:
star=LINESTRING(10 20, 20 20, ...)
square=POLYGON((10 10, ...))

?

Yep, that's the idea indeed

What do you think?

Well, while I clearly see the need for SVG, the implementation of this library looks to me like overstretching the requirement a bit... but it would be a rather elegant solution :slight_smile:

I've considered Batik too... but that piece of code (the "orphan" one) does
exactly what's needed, doesn't it ?

Err... no, I was just refererring to an idea, which is to let Batik
draw to a Graphics (which it can do) and have a special Graphics
implementation that steals the Shape objects passed down to it

Never programmed Batik, I will have to study it first.

One question: shall WKT and SVG be confined in a coordinate space of (-0.5 -0.5, 0.5 0.5) for the GraphicMark to work ?

The once had to be confined and be square, I know Milton removed the squareness requirement with one of his patches already, but I think
the shapes still need to be cehtered around 0... anyways, if they are not it's just a matter of creating a AffineTransform and apply it to the
shape to make it 0 centered

Cheers
Andrea

--
Andrea Aime
OpenGeo - http://opengeo.org
Expert service straight from the developers.