Java Drawing DrawTop

Language

JP  US  UK

 

Manipulating Shape

 H. Jyounishi, Tokyo Japan
 

Frame (Index), No frame                 version:0.3(latest)  

Summary:This page describes the operations of cutting shape and connecting curves.
Classes on this page: CutShape, CutShapeAction, ConnectCurves, ConnectCurvesAction, MouseHitShape


1. Cutting shape
1.1 Operation
(1) Samples

Original shapes An ellipse cut by a cubic curve Displaying the selection boxes

Figure 1.1 Sample of the operation


Figure 1.2 Sample of the operation


(2)The procedure of the operation See => Figure 1.3
∙ Select a target shape and a cutting shape (cutter).
∙ If the "Cut both shapes? yes" button is selected, the both shapes cut each other.
∙ Click the "Go" button, then the cutting operation will be performed displaying the intersection points of the blue marks.
The Repeat button is enabled. Another cutting operation can be performed by pressing the Repeat button.

Select a target shape and a cutting shape (cutter). Click the "Go" button.
The blue marks - intersection points.
The selection boxes of the result.
Click the Repeat Button, then the dialog returns to initial state.
Figure 1.3 Procedure of cutting operation


1.2 Class CutShape return=>page top
public class CutShape extends JDialog
Field Description
action
CutShapeAction action
Sets the CutShapeAction.
messageLabel1 JLabel messageLabel1
Sets the label object on which the showMessage methods displays a message.
messageLabel2 JLabel messageLabel2
Sets the label object on which the showMessage methods displays a message.
The messageLabel1 and messageLabel2 are placed in the upper and lower. When a message is long and is divided by \n, it will be displayed on the upper and lower labels.
goButton JButton goButton
The button object of "Go".
repeatButton JButton repeatButton
The button object of "Repeat".
cancelButton JButton cancelButton
The button object of "Cancel". This button isn't used now.
selectPanel JPanel selectPanel
The panel object of "cut both shapes? yes/no” buttons.
If the "yes/no" button are disabled, the title of the panel will be displayed with gray. If the "yes/no" button are enabled, the the title will be displayed with black.
yesButton RadioButton yesButton
The button object of "yes"
noButton JRadioButton noButton
The button object of "no"
shapeVector

Vector shapeVector
Stores the selected shapes.


Method Description
Constructor public CutShape() 
Calls the following methods.

super(ObjectTable.getDrawMain(), "cut shape");
this.setName("cut shape");
this.action=new CutShapeAction(this);
this.createDialog();

createDialog public void createDialog()
∙ Sets the dialog position at the left upper of the window.
∙ Adds the WindowListener to the dialog.

Before the window is closed, the windowClosing method calls the closeDialogmethod.

∙ Adds the components to the dialog.

Upper row: the message label.
Middle row: The panel in which "Go" and "Repeat" buttons are added.
Lower row: The panel of the "Cut both shapes?" label and the Æ"yes" "no" buttons.

∙ Set the CutShapetAction to the "Go" and "repeat" buttons as a ActionListener.
∙ Register the SelectionListener to SelectionLS to be able to receive selected shapes.
selectionLS.addSelectionListener(this);
showDialog public void showDialog(int commandId)
∙ Shows the dialog by setVisible method.
this.dialog.pack();
this.dialog.setVisible(true);
∙ If shapes are selected, then saves them to the shapeVector.

The selected shapes are checked whether they are appropriate or not by the isSutable method. If appropriate, then they are converted to new objects of the MouseHitShape and the MouseHitShape objects will be saved to the shapeVector.

setSelectPanel
Enable
protected void setSelectPanelEnable(boolean enable)
Parameters:
enable - If true, then the text and the buttons on the selectPanel are displayed with black. if false, then they are displayed with light gray which shows the buttons are disabled.
showMessage protected void showMessage(String message, Color color)
Parameter:
message - The message string.
color - The message color.
Processing:
Shows the message to the messageLabel.
getClickedShapes public MouseHitShape[] getClickedShapes() Returns all the MouseHitShape objects saved in the shapeVector.
This method is called by the CutShapeAction class.
selected public void selected(SelectionEvent event) Parameters:
event - SelectionEvent object.
Processing:
If a shape is selected by the mouse click in the SelectionLS, then this method called.
This method checks whether the selected shape is appropriate or not by isSuitable method. If appropriate, then this method creates a new object of the MouseHitShape and saves it to the shapeVector.
This method shows a message according to the number of the received shapes.

∙ The number equals 1: The message which requires to select a cutting shape.
∙ The number is more than or equal to 2: The message of "Go or Cancel".
In addition, this method makes the goButton enabled and calls the setSelectPanelEnable method.

this.goButton.setEnabled(true);
this.setSelectPanelEnable(true);

isSuitable private boolean isSuitable(ShapeContainer container)
Checks whether the shape denoted by container is appropriate or not for the cutting operation.
A shape with a text box and a group are inappropriate.
isDuplicated private int isDuplicated(ShapeContainer container)
Duplication check between a target shape and a cutter shape.
closeDialog private void closeDialog()
Close the dialog.
• Remove temporary marks and strings on the drawing panel.
• Remove the SelectionListener from SelectionLS.
windowClosing public void windowClosing(WindowEvent e)
Call the closeDialog method.


1.3 Class CutShapeAction return=>page top
class CutShapeAction extends AbstractAction implements WindowListener

The main purpose of this class is the operation of cutting a shape.

Field Description
dialog
CutShape dialog
Sets the CutShape object to this field.

Method Description
Constructor public CutShapeAction(CutShape dialog)
Sets the parameter to dialog field.
actionPerformed public void actionPerformed(ActionEvent e)
Executes the action processing of the clicked button.
∙ "Go" button

Calls the cutShapes method and the endProcess method.

∙ "Repeat" button

Calls the repeatProcess method.

∙ "Cancel" button

Calls the closeDialog method.

cutShapes private void cut()
∙ Calls the getIntersection method and displays the blue marks at the intersection points.

The getIntersection calls the Curve2DUtil.getIntersectionPts method to calculates the intersection points between the target shape and the cutting shape.

∙ Calls the cutContainer method to cut the target shape.

If the yesButton is selected, then this method also cuts the cutting shape.

∙ Undo setup.

Calls the ContainerManager.undoSetupStart method before cutting and calls the ContainerManager.undoSetupEnd method after cutting.
See => The undo support function of the ContainerManager.

getIntersection private CrossCurvePT[] getIntersection()
This method calls the Curve2DUtil.getIntersectionPts method to calculates the intersection points.
If intersection points are found, then this method returns the CrossCurvePT objects storing the intersection points, and display blue marks at the intersection points.
getExchangedData private CrossCurvePT[] getExchangedData(CrossCurvePT[] crossPTs)
This method exchanges the t1, t2 and the p1,p2 of the CrossCurvePT object.
cutContainer private ShapeContainer[] cutContainer(CrossCurvePT[] crossPTs, ShapeContainer targetContainer)
Parameters:
crossPTs - The intersection points between the target shape and the cutting shape.
targetContainer - The shape to be cut.
Returns:
The array of new ShapeContainer objects of the cut shapes.
Processing:
∙ Calls the getCutParams method to get the curve parameters of the intersection (cutting) points on the target shape.

The curve parameters arranged in ascending order.

∙ Calls the getTrimmedContainer method to create cut shapes one by one.
∙ Registers the cut shapes to the ContainerManager.
getCutParams private double[] getCutParams(Curve2D curve, double[] crossParams)
Parameters:
curve - The parametric curve of the target shape boundary.
crossParams - The parameters of the intersection points.
Returns:
The parameters representing cutting points.
Processing:
∙ Sorts the crossParams in ascendant order.

Let's denote the sorted crossParams as t0, t1, ..., tn-1 (t0<t1<...<tn-1).

∙ If the target shape has a open boundary, then returns the following parameters.

Returns ts, t0, t1, ..., tn-1, te. Here the ts is the start parameter of the parametric curve, and the te is the end parameter. The [ts,t0], [t0,t1],...[tn-1,te] represent the parameter intervals of new shapes to be created by the cutting operation.

∙ If the target shape has a closed boundary, then returns the following parameters.

Returns t0, t1, ..., tn-1, t0. The [t0,t1],...[tn-1,t0] represent the parameter intervals of new shapes to be created by the cutting operation.


Figure_(a) The open boundary Figure_(b) The closed boundary

getTrimmed
Container
private ShapeContainer getTrimmedContainer(ShapeContainer shapeContainer, double t1, double t2)
Parameters:
shapeContainer - The shape to be cut.
t1, t2 - The parameter interval of a new shape to be created.
Returns:
A trimmed curve of the new shape to be created.
Processing:
∙ Calls the Curve2DUtil.trimCurve2D method to cut the target shape boundary.

The case of t1>t2 is a special case corresponding to [t3,t0] interval in Figure_(a). The [t3,t0] interval contains the start point (ts) and the end point (te), so the trimmed curve of [t3,te] and that of [ts,t0] must be connected into one curve. This processing is performed by the trimCurve2D method.

∙ Changes the GeneralCurve2DE of the trimmed curve to simpler form, if possible.

The trimmed curve is represented by the GeneralCurve2DE class. However, if it is substantially a simpler form like a line, a polyline or a cubic curve, it will be changed to Line2DE, Polyline2DE or CubicCureve2DE.

endProcess private void endProcess()
Executes the ending process without closing dialog.
repeatProcess private void repeatProcess()
Set the dialog its initial state in order to execute a next cutting operation.
closeDialog private void closeDialog()
• Remove temporary marks and strings on the drawing panel.
• Remove the SelectionListener from SelectionLS.
windowClosing public void windowClosing(WindowEvent e)
Calls the closeDialog method.


2. Connecting curves return=>page top
The procedure
After the dialog opens, you have to select curves with clicking a mouse and press "Go" button, then a new curve will be created by connecting the selected curves on the condition that the new curve passes through the clicked points.

Selecting curves


Click "Go"button


Display the result.
Click the Repeat Button, then the dialog returns to initial state.
Figure 2.1 The procedure of connecting operation

The rules of the operation
This function creates a new curve by connecting the curve intervals of the selected curves. Each curve interval has to contain the corresponding clicked point inside. Let's denote the selected curves as C0, C1, C2,...Cn-1.
∙ If the intersection point is found between Ci-1 and Ci, then this function connects Ci-1 with Ci via the intersection point (Case (a) in the Figure 2.2).
∙ If no intersection point is found, then this function connects Ci-1 with Ci via a endpoint of one curve and a point on other curve (Case (b), (c)) or via endpoints of Ci-1 and Ci (Case (d)).

In the case (b), the connection point on the Ci (blue mark) is the nearest point from the end point of Ci-1. The case (c) is similar to the case (b). In the case (b), (c) and (d), the connection point of Ci-1 isn't equal to the connection point of Ci, therefore the Ci is transformed so that the both connection points occupy the same location.

∙ If the multiple intersection points are found between Ci-1 and Ci and some kind of route panning technique is required to connect curves, then this function outputs a error message (Case (e) in the Figure 2.3). The reason is that such complex case can be easily avoided by the operation of cutting shape.

Case (a) Case (b) Case (c) Case (d)

Figure 2.2 The cases of selecting the connection point





Case (e) Error Case (f) Successful

Figure 2.3 Error case and successful case


2.1 Class ConnectCurves return=>page top
Field Description
action
ConnectCurvesAction action

Sets the ConnectCurvesAction to this field.
instructionLabel JLabel instructionLabel
The label object displaying instruction.
messageLabel1 JLabel messageLabel1
Sets the label object on which the showMessage methods displays a message.
messageLabel2 JLabel messageLabel2
Sets the label object on which the showMessage methods displays a message.
The messageLabel1 and messageLabel2 are placed in the upper and lower. When a message is long and is divided by \n, it will be displayed on the upper and lower labels.
goButton JButton goButton:The button object of "Go".
repeatButton JButton repeatButton
The button object of "Repeat".
shapeVector Vector shapeVector
Stores the selected shapes.

Method Description
Constructor public ConnectCurves()
Calls the following methods.

super(ObjectTable.getDrawMain(), "connect curves");
this.setName("connect curves");
this.action=new ConnectCurvesAction(this);
this.createDialog();

createDialog public void createDialog()
∙ Sets the dialog position at the left upper of the window.
∙ Adds the WindowListener to the dialog.

Before the window is closed, the windowClosing method calls the closeDialog method.

∙ Adds the components to the dialog.

Upper row: The instruction label.
Middle row: The message label.
Lower row: The panel of the "Go" and "Cancel" buttons.

∙ Add the ConnectCurvestAction to the "Go" and "Cancel" buttons as a ActionListener.
∙ Register the SelectionListener to SelectionLS to be able to receive selected shapes.
selectionLS.addSelectionListener(this);
showDialog public void showDialog(int commandId)
∙ Shows the dialog by the following two lines.
this.pack();
this.setVisible(true);
showMessage protected void showMessage(String message, Color color)
Shows the message to the messageLabel.
selected public void selected(SelectionEvent event)
Parameters:
event - SelectionEvent object.
Processing:
If a shape is selected by the mouse click in the SelectionLS, then this method called.
This method checks whether the selected shape is appropriate or not by isSuitable method. If appropriate, then this method creates a new object of the MouseHitShape and saves it to the shapeVector.
This method shows a message according to the number of the received shapes.
isSuitable private boolean isSuitable(ShapeContainer container)
Checks whether the shape denoted by the container is appropriate or not for this operation.
Only a open curve is appropriate.
isDuplicated private int isDuplicated(ShapeContainer container)
Duplication check between selected curves.
closeDialog private void closeDialog()
• Remove temporary marks and strings on the drawing panel. • Remove the SelectionListener from SelectionLS.
getClickedShapes public MouseHitShape[] getClickedShapes()
Returns all the MouseHitShape objects saved in the shapeVector.
This method is called by the ConnectCurvesAction class.


2.2 Class ConnectCurvesAction return=>page top
Field Description
dialog
ConnectCurves dialog
Sets the ConnectCurves object to this field.

Method Description
Constructor public ConnectCurvesAction(CutShape dialog)
Sets the parameter to dialog field.
actionPerformed public void actionPerformed(ActionEvent e)
Executes the action processing of the clicked button.
∙ "Go" button

Calls the connect method.

∙ "Cancel" button

Calls the closeDialog method.

connect private int connect()
Returns: If the connecting operation fails, returns -1.
Processing:
∙ Calls the getConnectionPTs method and the checkConnectionPTs method.

If the return value of the checkConnectionPTs equals -1, then this method returns -1.

∙ Calls the createConnectedCurve method to create a new object of the connected curve.

Registers the connected curve to the ContainerManager, the the connected curve will be displayed on the canvas automatically.

∙ Undo setup.

Calls the ContainerManager.undoSetupStart method before registering and calls the ContainerManager.undoSetupEnd method after registering.
=> The undo support function of the ContainerManager.

getConnectionPTs private void getConnectionPTs(Vector connectionVector)
Parameters:
connectionVector - Stores the Connection objects which represent the connection points between the specified curves.
Processing:
∙ Retrieves the MouseHitShape objects by the ConnectCurves.getClickedShapes method.

Let's denote the selected curves saved in the MouseHitShape objects as C0, C1, C2,...Cn-1.

∙ Calls the calculateConnectionPTs method.

The calculateConnectionPTs method creates Connection objects which represent connection points between (Ci-1, Ci) i=1,n-1, and saves the Connection objects to the connectionVector.

∙ Displays blue marks at the connection points by the DrawShapeUtil.drawTempShape method.
calculate
ConnectionPTs

private void calculateConnectionPTs(ShapeContainer target1, ShapeContainer target2, double tolerance, Vector connectionVector)
Parameters:
target1 - The curve Ci-1 shown in the Figure 2.2.
target2 - The curve Ci shown in the Figure 2.2.
tolerance - The error margin by which two points are regarded as a connection point.
connectionVector - Stores the Connection objects which represent the connection points between the specified curves.
Processing:
This method calculates connection points between target1 and target2. Then it creates Connection objects representing the connection points and saves them to the connectionVector.
The connection points are calculated by the following two ways.
Case (a) of Figure 2.2

Calculates intersection points by the Curve2DUti.getIntersectionPts. In this case the intersection points are considered as connection points.

Case (b), (c), (d) of Figure 2.2

This method calculates the nearest point on the target2 from the endpoint of the target1 and the nearest point on the target1 from the endpoint of the target2 by the Curve2DUti.getShortestLine method. And this method chooses one from the nearest points, then the chosen nearest point and the endpoint of the target1 or target2 are considered as connection points. If the distance between the chosen nearest point and the endpoint is less than the tolerance (given by the parameter), then they are stored in a single Connection object.

checkConnectionPTs private int checkConnectionPTs()
Returns:
Returns -1, if the number of the specified curves is two, those are (C0, C1), and more than two connection points are found.
Return -1, if the number of the specified curves is more than two, those are (C0, C1, C2,...Cn-1, n≥3), and some couple of (Ci-1, Ci) has multiple connection points.
getConnections private Connection[] getConnections(ShapeContainer target1, ShapeContainer target2, Vector connectionVector)
Parameters:
target1 - The curve Ci-1 shown in the Figure 2.2.
target2 - The curve Ci shown in the Figure 2.2.
connectionVector - Stores the Connection objects which represent the connection points between the target1 and target2.
Returns:
The array of the Connection objects which connect the target1 with the target2.
getConnections private Connection[] getConnections(ShapeContainer target, Vector connectionVector)
Parameters:
target - The target curve.
connectionVector - Stores the Connection objects which represent the connection points between the specified curves.
Returns:
The array of the Connection objects which connect the target curve with any of the other curves.
createConnected
Curve
private ShapeContainer createConnectedCurve(Vector connectionVector)
Parameters:
connectionVector - Stores the Connection objects which represent the connection points between the specified curves.
Returns:
The connected curve.
Processing:
The curves to be connected are given by the MouseHitShape objects which are retrieved from the shapeVector by the getCrikedShapes method of the ConnectCurves.
∙ Calls the getCurveInterval method for each curve Ci.

The returned interval of the getCurveInterval method defines the trimmed curve of Ci which is a part of the connected curve. => The Figure of the getCurveInterval.

∙ Calls the Curve2DUti.trimCurve2D method to create the trimmed curve of Ci.
∙ Call the createConnectedCurve2D method to create the new object of the GeneralCurve2DE representing the connected curve.
∙ Changes the GeneralCurve2DE of the connected curve to simpler form, if possible.

If the connected curve is a polyline or a cubic curve, it will be changed to Polyline2DE or CubicCureve2DE.

∙ Stores the connected curve to the new object of the ShapeElement and stores the ShapeElement to the new object of the ShapeContainer.
createConnectedCurve2D private GeneralCurve2DE createConnectedCurve2D(GeneralCurve2DE trimmedCurve1, GeneralCurve2DE trimmedCurve2)
Parameters:
trimmedCurve1 - The parametric trimmed curve Ci-1.
trimmedCurve2 - The parametric trimmed curve Ci.
Returns:
The connected curve which is a parametric curve of the GeneralCurve2DE.
Processing:
∙ Changes the direction of the trimmedCurve1 and that of the trimmedCurve2 if necessary and connects the two curves.
∙ If the trimmedCurve1 and the trimmedCurve2 aren't continuous like the case (b), (c), (d) in the Figure 2.2, this method calls the ajustCurve method to make the two curve continuous by modifying the trimmedCurve2.
getCurveInterval private double[] getCurveInterval(ShapeContainer container, double clickedT, Vector connectionVector)
Parameters:
container - The selected curve Ci.
clickedT - The curve parameter of the clicked point.
connectionVector - Stores the objects which represent the connection points between the specified curves.
Returns:
The array storing the start parameter ts and end parameter te of the interval which includes the clickedT.
The interval [ts, te] defines the trimmed curve of Ci which is a part of the connected curve.

ajustCurve private void ajustCurve(GeneralCurve2DE targetCurve, GeneralCurve2DE anchorCurve)
Parameters:
targetCurve - The curve Ci.
anchorCurve - The curve Ci-1.
Processing:
If the anchorCurve and the targetCurve aren't continuous like the case (b), (c), (d) in the Figure 2.2, then this method transforms the targetCurve to make the two curves continuous.
The transforming is performed by the Matrix2D.getRotationMatrix method and the Curve2D.transform.
endProcess private void endProcess()
This method is called when the OK button is pressed.
• Deselect the selected shapes in the drawing panel (canvas).
• Clear the shapeVector
• Remove the SelectionListener from the SelectionLS.
repeatProcess private void repeatProcess()
This method is called when the Repeat button is pressed.
• Deselect the selected shapes in the drawing panel (canvas).
• Disable the Go button and the Repeat button.
• Clear the shapeVector
• Remove the SelectionListener from the SelectionLS.
closeDialog private void closeDialog()
• Remove temporary marks and strings on the drawing panel.
• Remove the SelectionListener from SelectionLS.
windowClosing public void windowClosing(WindowEvent e)
Calls the closeDialog method.


3. Class MouseHitShape return=>page top
In the CutShape and the ConnectCurves classes, the shapes to be manipulated are selected by the mouse clicks and the clicked points are important for the manipulation. The MouseHitShape class is used for storing the selected shape and the clicked point together.
Field Description
shapeContainer private ShapeContainer shapeContainer
The selected shape.
mousePosition private Point2D mousePosition
The mouse position.

Method Description
Constructor public MouseHitShape(ShapeContainer shapeContainer, Point2D mousePosition)
getShapeContainer public ShapeContainer getShapeContainer()
Returns the shapeContainer.
getMousePosition public Point2D getMousePosition()
Returns the mousePosition.
getCurveParameter public double getCurveParameter()
Returns the curve parameter of the mousePosition.
To get the curve parameter, this method calls the Curve2DUtil.getShortestLine method.
getEndIndexClose
ToMouse
public int getEndIndexCloseToMouse()
Returns the index (0/1) of the endpoint of the shapeContainer close to the mouse position.


Copyright (c) 2009-2013
All other trademarks are property of their respective owners.