Opened 20 years ago

Closed 20 years ago

#547 closed defect (wontfix)

Can't create a style object in Mapscript 4.0

Reported by: tmelhuish@… Owned by: sgillies@…
Priority: high Milestone:
Component: MapScript Version: 4.1
Severity: normal Keywords:
Cc: sgillies@…

Description

I can’t figure out how to create a new “style” object in mapscript under 4.0. 
Here is the code snippet that I’m using to create my “Style” object but the 
code dies at this line.

$layer = $map->getLayerByName($vars{ZoneMapQueryLayer})
$layer->{status} = $mapscript::MS_ON; # if it's not on already

	# SQL Call omitted
	#
	$ctr=0;
	while (@zone = ($stmt->fetchrow_array())) {

		${"Class"."$ctr"}= new mapscript::classObj($layer);
		$tmp=${"Class"."$ctr"};
		$Style= new mapscript::styleObj($tmp); # Bomb at this line
		#${"Style"."$ctr"}= new mapscript::styleObj($tmp);

                # Set $r,$g,$b Omitted
                #
		$Color= new mapscript::colorObj($Style);
		$Color->{red}= int($r);
		$Color->{green}= int($g);
		$Color->{blue}= int($b);
	}

To get around this I had to create a number of dummy classes with style & 
color in my map file and then overwrite them and it worked fine. Only issue is 
if I have more classes then dummies, the code will end with an error. This 
code snippet works:

	$layer = $map->getLayerByName($vars{ZoneMapQueryLayer})	$layer->
{status} = $mapscript::MS_ON; # if it's not on already

	# SQL Call omitted
	#
	$ctr=0;
	while (@zone = ($stmt->fetchrow_array())) {
		${"Class"."$ctr"}=$layer->getClass(($ctr));
		${"Class"."$ctr"}->{styles}->{color}->{red}= int($r);
		${"Class"."$ctr"}->{styles}->{color}->{green}= int($g);
		${"Class"."$ctr"}->{styles}->{color}->{blue}= int($b);
	}

++++++++++++++++++

Here is a “setExpression” in mapscript for anybody that is interested. This is 
not easy to figure out the syntax.

$expstr= qq((\'[zoning]\' eq \'$zone[0]\'));
	$rv = ${"Class"."$ctr"}->setExpression( $expstr );
#	$rv = ${"Class"."$ctr"}->setExpression('[zoning]' eq 'AR');

	$rv == $mapscript::MS_SUCCESS or &AppletMsg('can not setExpression in 
class ${"Class"."$ctr"} layer $layer',"error");

Change History (8)

comment:1 by sdlime, 20 years ago

Cc: sgillies@… added
Summary: Can't create a style object in Mapscript 4.0 Can't create a style object in Mapscript 4.0
Sean: What do you think? I think we just need a constructor in mapscript.i and 
a couple of helper methods.

Steve

comment:2 by sgillies@…, 20 years ago

Status: newassigned
Tom,

First, what do you mean by "Bomb at this line"?  We all know that your
computer program doesn't actually explode ... can you report the
actual error message?

Second, your code is in error: the styleObj constructor does _not_
take an argument.  You are making a similiar error further down
with the colorObj constructor which does not take a styleObj as
an argument.  (NB - In the 4.1 head CVS a colorObj can accept red,
green, and blue values as optional args like c = colorObj(r, g, b))

The styleObj class seems to be working properly in my MapScript
(4.1 head, but no significant changes from the styleObj in 4.0):

Python 2.3 (#6, Sep 14 2003, 15:46:16) 
[GCC 3.1 20020420 (prerelease)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from mapscript import *
>>> s = styleObj()
>>> s
<C styleObj instance at _00311dd0_p_styleObj>
>>> s.color
<C colorObj instance at _00311dd0_p_colorObj>
>>> s.color.red
0

The core problem here, IMO, is poor documentation of MapScript.  As one
of the main developers of the module, it's my fault as much as anyone
else.  Sorry that you are struggling with this.  Will you let us know
ASAP if the problem persists?

Steve, we should discuss reform of MapScript documentation in another
thread!

Sean

comment:3 by tmelhuish@…, 20 years ago

Sean,
I tried defining the style & color as shown below but I can't get anything for 
this layer to show. I'm running MS 4.0.1. My code runs fine with no errors. I 
must be missing something. If this looks right, how can I turn on some 
debugging so I can provide you more information to help resolve this problem.
++++++
      $Class= new mapscript::classObj($layer);
      $Style= new mapscript::styleObj();
      $Color= new mapscript::colorObj();

	$Class->{styles}=$Style;
	$Style->{color}=$Color;
	$Color->{red}= int($r);
	$Color->{green}= int($g);
	$Color->{blue}= int($b);
+++++
Thanks,
tom

comment:4 by sgillies@…, 20 years ago

Tom,

I think the code you should use looks like this:

  $classobj = new mapscript::classObj($layer);
  $classobj->{styles}->{color}->{red} = int($r);
  $classobj->{styles}->{color}->{green} = int($g);
  $classobj->{styles}->{color}->{blue} = int($b);

or more concisely,

  $classobj = new mapscript::classObj($layer);
  $classobj->{styles}->{symbol} = $symbol;   # need to define a symbol
  $c = $classobj->{styles}->{color};
  $c->{red} = int($r);
  $c->{green} = int($g);
  $c->{blue} = int($b);

A new classObj instance already has a styles attribute, so there's
no need to add a new one -- unless you really need multiple styles
to render the class.  And in this case, you're out of luck because
MapScript does not currently support multiple styles.  It would 
probably be a good idea to implement a getStyles() method for the
classObj class, but that is another issue.

Sean

comment:5 by sdlime, 20 years ago

I can't see how what exists can work without getStyle and newStyle methods in 
the classObj. Big oversight on my part when I added styles.

Steve

comment:6 by tmelhuish@…, 20 years ago

Sean,
I tried this early on with no luck:
  $classobj = new mapscript::classObj($layer);
  $classobj->{styles}->{color}->{red} = int($r);
  $classobj->{styles}->{color}->{green} = int($g);
  $classobj->{styles}->{color}->{blue} = int($b);

I know the classes are being created OK because the name shows up in my legend 
correclty but no colors are displayed. If I use getClass() to get the classes 
defined in the map file I need a minumum class definition in the map file of 
     CLASS
        STYLE
        END
     END
and then I can set the color with the lines you defined above. I even tried:
     $styleObj=$classObj->{styles}; 
but noticed that the code stopped running here with no error message. I know 
this because in my class loop I only get the first class defined and then it 
stops when it hits this line. I just don't think you can make the connection 
between the classObj you create and the associated styleObj that is created 
along with it without a getStyles() or something.

Thanks,
tom   


comment:7 by sgillies@…, 20 years ago

Owner: changed from sdlime to sgillies@…
Status: assignednew
Tom,

I have been able to replicate your problem with my Python MapScript,
and apologize for not checking it out in more detail earlier.

When a new classObj instance is created, it's styles attribute isn't
"live".  When you draw the layer, the new classification is not 
rendered.  When you save out the map file (mapobj.save()), the 
class on disk contains no STYLE blocks.

I'll pick up this bug and fix it before the next release.


comment:8 by sgillies@…, 20 years ago

Resolution: wontfix
Status: newclosed
Found the problem.

When a new classObj instance is created, the numstyles attribute is
by default 0.  Modifying the styles attribute does not change
numstyles, and so MapServer ignores the class.

The solution is to set numstyles after instantiating a classObj:

    new_classobj = mapscript.classObj(layerobj)
    new_classobj.numstyles = 1
    # Now modify new_classobj.styles
    ...

Of course, since numstyles _should_ be read-only, this is a hack
that we should avoid using.  Check out the issue 548
 
  http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=548

in which I will completely resolve the issues of multiple class
styles.

Note: See TracTickets for help on using tickets.