add Wedge patch

This commit is contained in:
wyq 2023-06-24 16:45:21 +08:00
parent 44d08ee8d1
commit 8c32998bec
9 changed files with 244 additions and 24 deletions

View File

@ -1049,8 +1049,8 @@ public class Plot2D extends AbstractPlot2D {
double height = this.projYLength(extent.getHeight(), area);
Float wedgeWidth = aShape.getWedgeWidth();
if (wedgeWidth == null) {
Draw.drawPie(new PointF((float)x, (float)y),
(float) width, (float) height, startAngle, sweepAngle, aPGB, g);
Draw.drawArc(new PointF((float)x, (float)y),
(float) width, (float) height, startAngle, sweepAngle, aPGB, g, aShape.getClosure());
} else {
wedgeWidth = (float)this.projXLength(wedgeWidth, area);
Draw.drawPie(new PointF((float)x, (float)y),

View File

@ -2495,8 +2495,7 @@ public class Draw {
break;
case ARC:
ArcShape arcShape = (ArcShape) aGraphic.getShape();
drawArc(points, arcShape.getAngle(), arcShape.getStartAngle(), arcShape.getSweepAngle(),
(PolygonBreak) aGraphic.getLegend(), g);
drawArc(points, arcShape, (PolygonBreak) aGraphic.getLegend(), g);
break;
}
@ -3943,6 +3942,32 @@ public class Draw {
}
}
/**
* Draw arc
*
* @param aPoint Start point
* @param width Width
* @param height Height
* @param startAngle Start angle
* @param sweepAngle Sweep angle
* @param aPGB Polygon break
* @param g Graphics2D
* @param type Closure type
*/
public static void drawArc(PointF aPoint, float width, float height, float startAngle, float sweepAngle,
PolygonBreak aPGB, Graphics2D g, int type) {
Color aColor = aPGB.getColor();
if (aPGB.isDrawFill()) {
g.setColor(aColor);
g.fill(new Arc2D.Float(aPoint.X, aPoint.Y, width, height, startAngle, sweepAngle, type));
}
if (aPGB.isDrawOutline()) {
g.setColor(aPGB.getOutlineColor());
g.setStroke(new BasicStroke(aPGB.getOutlineSize()));
g.draw(new Arc2D.Float(aPoint.X, aPoint.Y, width, height, startAngle, sweepAngle, type));
}
}
/**
* Draw pie
*
@ -4215,6 +4240,74 @@ public class Draw {
}
}
/**
* Draw Arc
*
* @param points The points
* @param angle The angle
* @param startAngle Arc start angle
* @param sweepAngle Arc sweep angle
* @param aPGB The polygon break
* @param g Graphics2D
* @param type Closure type
*/
public static void drawArc(PointF[] points, float angle, float startAngle, float sweepAngle,
PolygonBreak aPGB, Graphics2D g, int type) {
float sx = Math.min(points[0].X, points[2].X);
float sy = Math.min(points[0].Y, points[2].Y);
float width = Math.abs(points[2].X - points[0].X);
float height = Math.abs(points[2].Y - points[0].Y);
if (angle != 0) {
AffineTransform tempTrans = g.getTransform();
AffineTransform myTrans = (AffineTransform) tempTrans.clone();
myTrans.translate(sx + width / 2, sy + height / 2);
g.setTransform(myTrans);
Draw.drawArc(new PointF((float)sx, (float)sy),
(float) width, (float) height, startAngle, sweepAngle, aPGB, g, type);
g.setTransform(tempTrans);
} else {
Draw.drawArc(new PointF((float)sx, (float)sy),
(float) width, (float) height, startAngle, sweepAngle, aPGB, g, type);
}
}
/**
* Draw Arc
*
* @param points The points
* @param angle The angle
* @param startAngle Arc start angle
* @param sweepAngle Arc sweep angle
* @param aPGB The polygon break
* @param g Graphics2D
* @param type Closure type
*/
public static void drawArc(PointF[] points, ArcShape arcShape,
PolygonBreak legend, Graphics2D g) {
float sx = Math.min(points[0].X, points[2].X);
float sy = Math.min(points[0].Y, points[2].Y);
float width = Math.abs(points[2].X - points[0].X);
float height = Math.abs(points[2].Y - points[0].Y);
if (arcShape.getAngle() != 0) {
AffineTransform tempTrans = g.getTransform();
AffineTransform myTrans = (AffineTransform) tempTrans.clone();
myTrans.translate(sx + width / 2, sy + height / 2);
g.setTransform(myTrans);
Draw.drawArc(new PointF((float)sx, (float)sy), (float) width, (float) height,
arcShape.getStartAngle(), arcShape.getSweepAngle(), legend, g, arcShape.getClosure());
g.setTransform(tempTrans);
} else {
Draw.drawArc(new PointF((float)sx, (float)sy), (float) width, (float) height,
arcShape.getStartAngle(), arcShape.getSweepAngle(), legend, g, arcShape.getClosure());
}
}
/**
* Draw selected vertices rectangles
*

View File

@ -1943,7 +1943,7 @@ public class DrawMeteoData {
aPoint.X = xIter.getDoubleNext();
aPoint.Y = yIter.getDoubleNext();
v = iter.getDoubleNext();
if (Double.isNaN(aPoint.X) || Double.isNaN(aPoint.Y)) {
if (Double.isNaN(aPoint.X) || Double.isNaN(aPoint.Y) || Double.isNaN(v)) {
continue;
}
PointShape aPointShape = new PointShape();

View File

@ -383,6 +383,24 @@ public class GraphicCollection extends Graphic implements Iterator {
*/
public void addAll(List<Graphic> gs) {
this.graphics.addAll(gs);
// Update extent
int i = 0;
Extent extent;
for (Graphic g : gs) {
if (g instanceof GraphicCollection) {
extent = g.getExtent();
} else {
extent = g.getShape().getExtent();
}
if (i == 0) {
_extent = extent;
} else {
_extent = MIMath.getLagerExtent(_extent, extent);
}
i += 1;
}
}
/**

View File

@ -15,6 +15,7 @@ package org.meteoinfo.geometry.shape;
import org.meteoinfo.common.PointD;
import java.awt.geom.Arc2D;
import java.util.ArrayList;
import java.util.List;
@ -28,6 +29,7 @@ public class ArcShape extends EllipseShape {
private float sweepAngle;
private float explode = 0;
private Float wedgeWidth = null;
private int closure = Arc2D.PIE;
// </editor-fold>
// <editor-fold desc="Constructor">
/**
@ -122,6 +124,22 @@ public class ArcShape extends EllipseShape {
public void setWedgeWidth(Float value) {
this.wedgeWidth = value;
}
/**
* Get closure type
* @return Closure type
*/
public int getClosure() {
return this.closure;
}
/**
* Set closure type
* @param value Closure type
*/
public void setClosure(int value) {
this.closure = value;
}
// </editor-fold>
// <editor-fold desc="Methods">
@ -166,6 +184,13 @@ public class ArcShape extends EllipseShape {
aPGS.setPoints(new ArrayList<>(this.getPoints()));
aPGS.setVisible(this.isVisible());
aPGS.setSelected(this.isSelected());
aPGS.setClosure(this.closure);
aPGS.setExplode(this.explode);
aPGS.setStartAngle(this.startAngle);
aPGS.setSweepAngle(this.sweepAngle);
aPGS.setAngle(this.angle);
aPGS.setWedgeWidth(this.wedgeWidth);
aPGS.setLegendIndex(this.getLegendIndex());
return aPGS;
}

View File

@ -1,34 +1,36 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MeteoInfo File="milconfig.xml" Type="configurefile">
<Path OpenPath="D:\Working\MIScript\Jython\mis\io\micaps">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\savefig"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\dataframe"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\contour"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\contour"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\streamplot"/>
<Path OpenPath="D:\Working\MIScript\Jython\mis\plot_types\patch">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite\omi"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\wind"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\pie"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\micaps"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map\topology"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\array"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\plot"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\radar"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map\projection"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\surf"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\funny"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\micaps"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\patch"/>
</Path>
<File>
<OpenedFiles>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\_reload.py"/>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\mainGUI.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\contour\contour3_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\io\micaps\mdfs_dataframe_2.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\patch\wind_circle_2.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\patch\wind_circle_1.py"/>
</OpenedFiles>
<RecentFiles>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\_reload.py"/>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\mainGUI.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\contour\contour3_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\io\micaps\mdfs_dataframe_2.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\patch\wind_circle_2.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\patch\wind_circle_1.py"/>
</RecentFiles>
</File>
<Font>
@ -36,5 +38,5 @@
</Font>
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/>
<Figure DoubleBuffering="true"/>
<Startup MainFormLocation="-7,0" MainFormSize="1399,787"/>
<Startup MainFormLocation="-7,-7" MainFormSize="1293,685"/>
</MeteoInfo>

View File

@ -1052,9 +1052,12 @@ class Axes(object):
"""
Add a patch.
:param patch: (*Graphic*) The patch to be added.
:param patch: (*Graphic or list of graphics*) The patch(s) to be added.
"""
self._axes.addGraphic(patch)
if isinstance(patch, (list, tuple)):
self._axes.addGraphics(patch)
else:
self._axes.addGraphic(patch)
self._axes.setAutoExtent()
def add_graphic(self, graphic, projection=None, zorder=None):

View File

@ -5,7 +5,7 @@ from org.meteoinfo.geometry.shape import ShapeUtil, CircleShape, EllipseShape, \
from . import plotutil
import mipylib.numeric as np
__all__ = ['Arc','Circle','Ellipse','Rectangle','Polygon']
__all__ = ['Arc','Circle','Ellipse','Rectangle','Polygon','Wedge']
class Circle(Graphic):
"""
@ -87,6 +87,7 @@ class Arc(Graphic):
:param angle: (float) Ellipse angle. Default is `0`.
:param theta1: (float) Starting angle of the arc in degrees. Default is `0.0`.
:param theta2: (float) Ending angle of the arc in degrees. Default is `360`.
:param closure: (str) Closure type ['open' | 'chord' | 'pie']. Default is `pie`.
"""
self._center = xy
self._width = width
@ -98,6 +99,19 @@ class Arc(Graphic):
shape.setAngle(angle)
shape.setStartAngle(theta1)
shape.setSweepAngle(theta2 - theta1)
self._closure = kwargs.pop('closure', None)
if self._closure is None:
self._closure = 'pie'
else:
if self._closure == 'open':
closure = 0
elif self._closure == 'chord':
closure = 1
else:
self._closure = 'pie'
closure = 2
shape.setClosure(closure)
legend, isunique = plotutil.getlegendbreak('polygon', **kwargs)
super(Arc, self).__init__(shape, legend)
@ -125,6 +139,71 @@ class Arc(Graphic):
def theta2(self):
return self._theta2
@property
def closure(self):
return self._closure
class Wedge(Graphic):
"""
Wedge shaped patch.
A wedge centered at x, y center with radius r that sweeps theta1 to theta2 (in degrees). If width is
given, then a partial wedge is drawn from inner radius r - width to outer radius r.
"""
def __init__(self, center, r, theta1, theta2, **kwargs):
"""
Create an arc at anchor point *xy* = (*x*, *y*) with given *width* and *height*.
:param center: (float, float) xy coordinates of wedge center point.
:param r: (float) Radius.
:param theta1: (float) Starting angle of the arc in degrees.
:param theta2: (float) Ending angle of the arc in degrees.
:param closure: (str) Closure type ['open' | 'chord' | 'pie']. Default is `pie`.
"""
self._center = center
self._r = r
self._theta1 = theta1
self._theta2 = theta2
shape = ArcShape(center[0], center[1], r * 2, r * 2)
shape.setStartAngle(theta1)
shape.setSweepAngle(theta2 - theta1)
self._closure = kwargs.pop('closure', None)
if self._closure is None:
self._closure = 'pie'
else:
if self._closure == 'open':
closure = 0
elif self._closure == 'chord':
closure = 1
else:
self._closure = 'pie'
closure = 2
shape.setClosure(closure)
legend, isunique = plotutil.getlegendbreak('polygon', **kwargs)
super(Wedge, self).__init__(shape, legend)
@property
def center(self):
return self._center
@property
def r(self):
return self._r
@property
def theta1(self):
return self._theta1
@property
def theta2(self):
return self._theta2
@property
def closure(self):
return self._closure
class Rectangle(Graphic):
"""
A rectangle patch.