View Javadoc

1   /**********************************************
2    * Copyright (C) 2011 Lukas Laag
3    * This file is part of svgreal.
4    * 
5    * svgreal is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    * 
10   * svgreal is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   * 
15   * You should have received a copy of the GNU General Public License
16   * along with svgreal.  If not, see http://www.gnu.org/licenses/
17   **********************************************/
18  package org.vectomatic.svg.edit.client.command.path;
19  
20  import org.vectomatic.dom.svg.OMSVGCircleElement;
21  import org.vectomatic.dom.svg.OMSVGDocument;
22  import org.vectomatic.dom.svg.OMSVGLineElement;
23  import org.vectomatic.dom.svg.OMSVGMatrix;
24  import org.vectomatic.dom.svg.OMSVGPathSeg;
25  import org.vectomatic.dom.svg.OMSVGPathSegCurvetoCubicAbs;
26  import org.vectomatic.dom.svg.OMSVGPoint;
27  import org.vectomatic.svg.edit.client.command.path.IPathRepOwner.Mode;
28  
29  import com.google.gwt.dom.client.Element;
30  
31  /**
32   * Class to represent a path cubic segment 
33   * @author laaglu
34   */
35  public class SVGCubicSegRep extends SVGSegRep {
36  	protected OMSVGPathSegCurvetoCubicAbs cubicToSeg;
37  	protected OMSVGCircleElement cp1;
38  	protected OMSVGCircleElement cp2;
39  	protected OMSVGLineElement tg1;
40  	protected OMSVGLineElement tg2;
41  
42  	public SVGCubicSegRep(IPathRepOwner owner, OMSVGPathSegCurvetoCubicAbs cubicToSeg) {
43  		super(owner);
44  		this.cubicToSeg = cubicToSeg;
45  		
46  		// Create the tangents
47  		OMSVGDocument document = (OMSVGDocument) owner.getSvg().getOwnerDocument();
48  		cp1 = document.createSVGCircleElement();
49  		cp2 = document.createSVGCircleElement();
50  		tg1 = document.createSVGLineElement();
51  		tg2 = document.createSVGLineElement();
52  		tangents.appendChild(tg1);
53  		tangents.appendChild(tg2);
54  		tangents.appendChild(cp1);
55  		tangents.appendChild(cp2);
56  	}
57  	
58  	@Override
59  	public OMSVGPathSeg getElement() {
60  		return cubicToSeg;
61  	}
62  	
63  	@Override
64  	public float getX() {
65  		return cubicToSeg.getX();
66  	}
67  	@Override
68  	public void setX(float x) {
69  		cubicToSeg.setX(x);
70  	}
71  	@Override
72  	public float getY() {
73  		return cubicToSeg.getY();
74  	}
75  	@Override
76  	public void setY(float y) {
77  		cubicToSeg.setY(y);
78  	}
79  	@Override
80  	public float getX1() {
81  		return cubicToSeg.getX1();
82  	}
83  	@Override
84  	public float getY1() {
85  		return cubicToSeg.getY1();
86  	}
87  	@Override
88  	public float getX2() {
89  		return cubicToSeg.getX2();
90  	}
91  	@Override
92  	public float getY2() {
93  		return cubicToSeg.getY2();
94  	}
95  	@Override
96  	public Element getCp1() {
97  		return cp1.getElement();
98  	}
99  	@Override
100 	public void setCp1(OMSVGPoint p, float hs) {
101 		cubicToSeg.setX1(p.getX());
102 		cubicToSeg.setY1(p.getY());
103 		update(hs);
104 	}
105 	@Override
106 	public Element getCp2() {
107 		return cp2.getElement();
108 	}
109 	@Override
110 	public void setCp2(OMSVGPoint p, float hs) {
111 		cubicToSeg.setX2(p.getX());
112 		cubicToSeg.setY2(p.getY());
113 		update(hs);
114 	}
115 
116 	@Override
117 	public void update(float hs) {
118 		float x = cubicToSeg.getX();
119 		float y = cubicToSeg.getY();
120 		vertex.getX().getBaseVal().setValue(x - hs);
121 		vertex.getY().getBaseVal().setValue(y - hs);
122 		vertex.getWidth().getBaseVal().setValue(hs * 2);
123 		vertex.getHeight().getBaseVal().setValue(hs * 2);
124 		if (owner.getMode() == Mode.TANGENT) {
125 			float px = previous != null ? previous.getX() : 0;
126 			float py = previous != null ? previous.getY() : 0;
127 			float x1 = cubicToSeg.getX1();
128 			float y1 = cubicToSeg.getY1();
129 			float x2 = cubicToSeg.getX2();
130 			float y2 = cubicToSeg.getY2();
131 			tg1.getX1().getBaseVal().setValue(px);
132 			tg1.getY1().getBaseVal().setValue(py);
133 			tg1.getX2().getBaseVal().setValue(x1);
134 			tg1.getY2().getBaseVal().setValue(y1);
135 			
136 			tg2.getX1().getBaseVal().setValue(x);
137 			tg2.getY1().getBaseVal().setValue(y);
138 			tg2.getX2().getBaseVal().setValue(x2);
139 			tg2.getY2().getBaseVal().setValue(y2);
140 			
141 			cp1.getCx().getBaseVal().setValue(x1);
142 			cp1.getCy().getBaseVal().setValue(y1);
143 			cp1.getR().getBaseVal().setValue(hs);
144 	
145 			cp2.getCx().getBaseVal().setValue(x2);
146 			cp2.getCy().getBaseVal().setValue(y2);
147 			cp2.getR().getBaseVal().setValue(hs);
148 		}
149 	}
150 
151 	@Override
152 	public void updateStart(OMSVGPoint delta, float hs) {
153 		cubicToSeg.setX1(cubicToSeg.getX1() + delta.getX());
154 		cubicToSeg.setY1(cubicToSeg.getY1() + delta.getY());
155 		update(hs);
156 	}
157 	
158 	@Override
159 	public void updateEnd(OMSVGPoint delta, float hs) {
160 		cubicToSeg.setX2(cubicToSeg.getX2() + delta.getX());
161 		cubicToSeg.setY2(cubicToSeg.getY2() + delta.getY());
162 		cubicToSeg.setX(cubicToSeg.getX() + delta.getX());
163 		cubicToSeg.setY(cubicToSeg.getY() + delta.getY());
164 		update(hs);
165 	}
166 
167 	@Override
168 	public void processMouseMove(OMSVGPoint delta, Element target, float hs, boolean isCtrlKeyDown) {
169 		if (target == null || tg2.getElement() == target) {
170 			updateEnd(delta, hs);
171 			if (next != null) {
172 				next.updateStart(delta, hs);
173 			}
174 		} else if (tg1.getElement() == target) {
175 			updateStart(delta, hs);
176 			if (previous != null) {
177 				previous.updateEnd(delta, hs);
178 			}
179 		} else if (cp1.getElement() == target) {
180 			SVGSegRep prevSeg = getPreviousSplineSeg();
181 			Float angle = null;
182 			if (isCtrlKeyDown && prevSeg != null) {
183 				// Compute the angle between the tangent and the updated tangent
184 				OMSVGPoint v1 = owner.getSvg().createSVGPoint(
185 						cubicToSeg.getX1() - prevSeg.getX(),
186 						cubicToSeg.getY1() - prevSeg.getY());
187 				OMSVGPoint v2 = owner.getSvg().createSVGPoint(
188 						cubicToSeg.getX1() + delta.getX() - prevSeg.getX(),
189 						cubicToSeg.getY1() + delta.getY() - prevSeg.getY());
190 				float d = v1.length() * v2.length();
191 				if (d != 0) {
192 					angle = (float)(Math.acos(v1.dotProduct(v2) / d) * 180 / Math.PI);						
193 					if (v1.crossProduct(v2) < 0) {
194 						angle = 360 - angle;
195 					}
196 				}
197 			}
198 			cubicToSeg.setX1(cubicToSeg.getX1() + delta.getX());
199 			cubicToSeg.setY1(cubicToSeg.getY1() + delta.getY());
200 			update(hs);
201 			if (angle != null) {
202 				// Apply the same rotation to the next spline tangent
203 				OMSVGMatrix m = owner.getSvg().createSVGMatrix();
204 				m = m.translate(prevSeg.getX(), prevSeg.getY());
205 				m = m.rotate(angle);
206 				m = m.translate(-prevSeg.getX(), -prevSeg.getY());
207 				OMSVGPoint p0 = owner.getSvg().createSVGPoint(
208 						prevSeg.getX2(),
209 						prevSeg.getY2());
210 				OMSVGPoint p1 = p0.matrixTransform(m).substract(p0);
211 				prevSeg.processMouseMove(p1, prevSeg.getCp2(), hs, false);
212 			}
213 		} else if (cp2.getElement() == target) {
214 			SVGSegRep nextSeg = getNextSplineSeg();
215 			Float angle = null;
216 			if (isCtrlKeyDown && next != null) {
217 				// Compute the angle between the tangent and the updated tangent
218 				OMSVGPoint v1 = owner.getSvg().createSVGPoint(
219 						cubicToSeg.getX2() - cubicToSeg.getX(),
220 						cubicToSeg.getY2() - cubicToSeg.getY());
221 				OMSVGPoint v2 = owner.getSvg().createSVGPoint(
222 						cubicToSeg.getX2() + delta.getX() - cubicToSeg.getX(),
223 						cubicToSeg.getY2() + delta.getY() - cubicToSeg.getY());
224 				float d = v1.length() * v2.length();
225 				if (d != 0) {
226 					angle = (float)(Math.acos(v1.dotProduct(v2) / d) * 180 / Math.PI);						
227 					if (v1.crossProduct(v2) < 0) {
228 						angle = 360 - angle;
229 					}
230 				}
231 			}
232 			cubicToSeg.setX2(cubicToSeg.getX2() + delta.getX());
233 			cubicToSeg.setY2(cubicToSeg.getY2() + delta.getY());
234 			update(hs);
235 			if (angle != null) {
236 				// Apply the same rotation to the next spline tangent
237 				OMSVGMatrix m = owner.getSvg().createSVGMatrix();
238 				m = m.translate(cubicToSeg.getX(), cubicToSeg.getY());
239 				m = m.rotate(angle);
240 				m = m.translate(-cubicToSeg.getX(), -cubicToSeg.getY());
241 				OMSVGPoint p0 = owner.getSvg().createSVGPoint(
242 						nextSeg.getX1(),
243 						nextSeg.getY1());
244 				OMSVGPoint p1 = p0.matrixTransform(m).substract(p0);
245 				nextSeg.processMouseMove(p1, nextSeg.getCp1(), hs, false);
246 			}
247 		}
248 	}
249 	
250 	@Override
251 	public String toString() {
252 		StringBuilder builder = new StringBuilder("C ");
253 		builder.append(cubicToSeg.getX1());
254 		builder.append(",");
255 		builder.append(cubicToSeg.getY1());
256 		builder.append(" ");
257 		builder.append(cubicToSeg.getX2());
258 		builder.append(",");
259 		builder.append(cubicToSeg.getY2());
260 		builder.append(" ");
261 		builder.append(cubicToSeg.getX());
262 		builder.append(",");
263 		builder.append(cubicToSeg.getY());
264 		return builder.toString();
265 	}
266 }