简体   繁体   中英

Serialize a java.awt.geom.Area

I have the need to serialize an Area object (java.awt.geom.Area) in a socket. However it doesn't seem to be serializable. Is there a way to do such thing? Maybe by converting it into a different object?

Thanks in advance

I found this workaround:

AffineTransform.getTranslateInstance(0,0).createTransformedShape(myArea)

This results in a shape that can be serialized.

Use XStream to trivially convert it to/from XML. You don't need your object to implement particular interfaces, and the serialisation is customisable.

From kieste's answer, this work-around can be derived.

import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.io.IOException;
import java.io.Serializable;

public class SerialArea extends Area implements Serializable {
    private static final long serialVersionUID = -3627137348463415558L;

    /**
     * New Area
     */
    public SerialArea() {}

    /**
     * New Area From Shape
     */
    public SerialArea(Shape s) {
        super(s);
    }

    /**
     * Writes object out to out.
     * @param out Output
     * @throws IOException if I/O errors occur while writing to the
     *  underlying OutputStream
     */
    private void writeObject(java.io.ObjectOutputStream out)
            throws IOException {
        out.writeObject(AffineTransform.getTranslateInstance(0, 0).
            createTransformedShape(this));
    }
    /**
     * Reads object in from in.
     * @param in Input
     * @throws IOException if I/O errors occur while writing to the
     *  underlying OutputStream
     * @throws ClassNotFoundException if the class of a serialized object
     *  could not be found.
     */
    private void readObject(java.io.ObjectInputStream in)
            throws IOException, ClassNotFoundException {
        add(new Area((Shape) in.readObject()));
    }
}

Since Java 1.6 seems like there is a more formal way of doing this.

All you have to do is convert the Area object to a Path2D.Double (or Path2D.Float ) object (which is Serializable ) with its corresponding append method, taking also into account the winding rule at construction time (or even later, with a corresponding setter that exists).

To convert from Path2D.Double to Area , just use the Area 's constructor which accepts a Shape .

import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;

public class SerializeArea {

    public static Path2D.Double toPath2D(final Area a) {
        final PathIterator pi = a.getPathIterator(new AffineTransform());
        final Path2D.Double path = new Path2D.Double();
        switch (pi.getWindingRule()) {
            case PathIterator.WIND_EVEN_ODD: path.setWindingRule(Path2D.WIND_EVEN_ODD); break;
            case PathIterator.WIND_NON_ZERO: path.setWindingRule(Path2D.WIND_NON_ZERO); break;
            default: throw new UnsupportedOperationException("Unimplemented winding rule.");
        }
        path.append(pi, false);
        return path;
    }

    public static Area toArea(final Path2D path) {
        return new Area(path);
    }

    public static void main(final String[] args) {
        final Area area = new Area(new Ellipse2D.Double(0, 0, 100, 100));
        area.intersect(new Area(new Rectangle2D.Double(0, 25, 100, 50))); //Creating something like a capsule.

        System.out.println(toArea(toPath2D(area)).equals(area)); //Prints true.
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM