Select to view content in your preferred language

Creating composite symbol to group different symbols

4797
6
12-15-2012 11:12 PM
ManjiriJoshi
New Contributor
My requirement it to group different symbols together like simple marker,pictureMarkerSymbol etc.
How to achive this in new api??
0 Kudos
6 Replies
MarkBaird
Esri Regular Contributor
We currently don't have a composite symbol in the API.  If I can gather requirements then this can be considered for a future release.

At the moment graphics (of all supported types) can be contained in a graphics layer.

A graphics layer can be contained either in a group layer, or directly in a JMap control.
0 Kudos
CarlosColón-Maldonado
Frequent Contributor
Your current and only choice is to use the com.esri.core.symbol interface since all mentioned types implement it. Optionally, you could create a wrapper which contains this interface type, but it will take some research to determine if it suits your needs.

hope this helps.

[ATTACH=CONFIG]20593[/ATTACH]

http://resources.arcgis.com/en/help/runtime-java/apiref/index.html
0 Kudos
CarlosColón-Maldonado
Frequent Contributor
We currently don't have a composite symbol in the API.  If I can gather requirements then this can be considered for a future release.


Hi Mark. Congratulations on the implementation of the composite symbol.

Now that it's here, and there is no concrete example in Java, I was wondering if you could provide the how to compose a picture maker symbol, a simple line symbol, and a text symbol relation where the composite symbol can be manipulated to reposition about the map without affecting their corresponding locations with respect to each.

Thanks!
0 Kudos
MarkBaird
Esri Regular Contributor
The sample application shows you how you can create a composite symbol made up from a few different things.

Open the sample application and select Graphics Layers -> add graphics.

Does this answer your question?

Mark
0 Kudos
CarlosColón-Maldonado
Frequent Contributor
The sample application shows you how you can create a composite symbol made up from a few different things.


Thank you for pointing it out, didn't pay attention to the added samples.

Does this answer your question?


Perhaps, but it seems to me that, by the behavior of how the graphics layer handles/tracks its graphics, the composite symbol cannot be tracked as a single graphic, but a combination of a polygon and polyline of graphics when a line symbol is added.

My requirement is to add a line (shown as a "tail", with an arrow head, off a symbol) based on a direction of travel, or an angle with respect to north, that can be modified if the direction of travel changes (see pic). My observation above tells me that I would have to track two graphics within a a layer where I had always needed to track only one. Any suggestions on how I can pull this off?
0 Kudos
CarlosColón-Maldonado
Frequent Contributor
I'd like to report that, with the help of ESRI support, the solution to implement the adding of a line with an arrow head off a symbol to depict the symbol's direction of travel, or an angle with respect to north, that can be modified if the direction of travel changes was achieved. It can be accomplished without the need to create additional graphics, thus avoiding multiple graphic tracking off a single composite symbol. The code is below:
    /**
     * Sets the direction of travel property on this symbol
     * 
     * @param angle The direction of travel to set.
     * @param angularUnit The units for the direction of travel.
     */
    public void setDirectionOfTravel(double angle, AngularUnit angularUnit) {
        this.symbols.remove(this.directionOfTravel);
        this.symbols.remove(this.directionOfTravelGroundLine);
        
        double radians = swapCompassHeadingAndTrigAngle(Code.RADIAN == angularUnit.getID() ? angle : angularUnit.convertToRadians(angle));
        
        boolean isGround = 'G' == this.sic.charAt(2) || 'g' == this.sic.charAt(2); 
        if (isGround) {
            //Battle dimension is Ground; draw line straight down behind frame
            BufferedImage groundImage = new BufferedImage(DIRECTION_LINE_THICKNESS, DIRECTION_OF_MOVEMENT_LENGTH, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = groundImage.createGraphics();
            g.setBackground(Color.BLACK);
            this.directionOfTravelGroundLine = new PictureMarkerSymbol(groundImage);
            this.directionOfTravelGroundLine.setOffsetY(DIRECTION_OF_MOVEMENT_LENGTH / -2);
            this.symbols.add(0, this.directionOfTravelGroundLine);
            this.updateSymbol();
        }
        //Draw arrow directly from center and on top of frame
        double x = DIRECTION_OF_MOVEMENT_LENGTH * Math.cos(radians);
        double y = DIRECTION_OF_MOVEMENT_LENGTH * Math.sin(radians);
        BufferedImage directionImage = new BufferedImage(2 * DIRECTION_OF_MOVEMENT_LENGTH, 2 * DIRECTION_OF_MOVEMENT_LENGTH, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = directionImage.createGraphics();
        g.setColor(Color.BLACK);
        g.setStroke(new BasicStroke(DIRECTION_LINE_THICKNESS));
        g.drawLine(DIRECTION_OF_MOVEMENT_LENGTH, 
                   DIRECTION_OF_MOVEMENT_LENGTH,
                   DIRECTION_OF_MOVEMENT_LENGTH + (int) Math.round(x),
                   DIRECTION_OF_MOVEMENT_LENGTH - (int) Math.round(y));
        double firstArrowAngle = radians + Math.PI + DIRECTION_ARROWHEAD_ANGLE;
        double firstArrowX = DIRECTION_ARROWHEAD_HEIGHT * Math.cos(firstArrowAngle);
        double firstArrowY = DIRECTION_ARROWHEAD_HEIGHT * Math.sin(firstArrowAngle);
        double secondArrowAngle = radians + Math.PI - DIRECTION_ARROWHEAD_ANGLE;
        double secondArrowX = DIRECTION_ARROWHEAD_HEIGHT * Math.cos(secondArrowAngle);
        double secondArrowY = DIRECTION_ARROWHEAD_HEIGHT * Math.sin(secondArrowAngle);
        g.fillPolygon(new int[] {
            DIRECTION_OF_MOVEMENT_LENGTH + (int) Math.round(x),
            DIRECTION_OF_MOVEMENT_LENGTH + (int) Math.round(x) + (int) Math.round(firstArrowX),
            DIRECTION_OF_MOVEMENT_LENGTH + (int) Math.round(x) + (int) Math.round(secondArrowX)},
            new int[] {
                DIRECTION_OF_MOVEMENT_LENGTH - (int) Math.round(y),
                DIRECTION_OF_MOVEMENT_LENGTH - (int) Math.round(y) - (int) Math.round(firstArrowY),
                DIRECTION_OF_MOVEMENT_LENGTH - (int) Math.round(y) - (int) Math.round(secondArrowY)},
                3);
        this.directionOfTravel = new PictureMarkerSymbol(directionImage);
        if (isGround) {
            this.directionOfTravel.setOffsetY(-1 * DIRECTION_OF_MOVEMENT_LENGTH);
        }
        this.symbols.add(this.directionOfTravel);
        this.updateSymbol();
    }

The above method is off a class that extends the composite symbol and, thus have access to all of list of symbols. The "updateSymbol" method simply removes and re-adds all enclosing symbols to the composite symbol, and updates its graphics layer using its graphic id. The "checking" of the "G" of the military symbol identification code determines if the composite symbol is that of a "Ground" entity, which, by standards, the arrowed line must comes off the bottom of the symbol and then to the direction of travel, whereas all others starts from the center of the symbol. The method uses images instead to "paint" the line and arrow to depict the desire look-and-feel. Note that, with the use of the composite symbol on screenshot of the variety are attached, additional missing labels can be implemented that are not currently seen or available using the message processor. The symbol image can also be modified to depict currency or status of symbols seen in military field systems.

Excellent work, ESRI!