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.OMSVGPathSegCurvetoQuadraticAbs;
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 quadratic segment 
33   * @author laaglu
34   */
35  public class SVGQuadraticSegRep extends SVGSegRep {
36  	protected OMSVGPathSegCurvetoQuadraticAbs quadraticToSeg;
37  	protected OMSVGCircleElement cp;
38  	protected OMSVGLineElement tg1;
39  	protected OMSVGLineElement tg2;
40  
41  	public SVGQuadraticSegRep(IPathRepOwner owner, OMSVGPathSegCurvetoQuadraticAbs quadraticToSeg) {
42  		super(owner);
43  		this.quadraticToSeg = quadraticToSeg;
44  		
45  		// Create the controls
46  		OMSVGDocument document = (OMSVGDocument) owner.getSvg().getOwnerDocument();
47  		cp = document.createSVGCircleElement();
48  		tg1 = document.createSVGLineElement();
49  		tg2 = document.createSVGLineElement();
50  		tangents.appendChild(tg1);
51  		tangents.appendChild(tg2);
52  		tangents.appendChild(cp);
53  	}
54  
55  	@Override
56  	public OMSVGPathSeg getElement() {
57  		return quadraticToSeg;
58  	}
59  
60  	@Override
61  	public float getX() {
62  		return quadraticToSeg.getX();
63  	}
64  	@Override
65  	public void setX(float x) {
66  		quadraticToSeg.setX(x);
67  	}
68  	@Override
69  	public float getY() {
70  		return quadraticToSeg.getY();
71  	}
72  	@Override
73  	public void setY(float y) {
74  		quadraticToSeg.setY(y);
75  	}
76  	@Override
77  	public float getX1() {
78  		return quadraticToSeg.getX1();
79  	}
80  	@Override
81  	public float getY1() {
82  		return quadraticToSeg.getY1();
83  	}
84  	@Override
85  	public float getX2() {
86  		return getX1();
87  	}
88  	@Override
89  	public float getY2() {
90  		return getY1();
91  	}
92  	@Override
93  	public Element getCp1() {
94  		return cp.getElement();
95  	}
96  	@Override
97  	public void setCp1(OMSVGPoint p, float hs) {
98  		quadraticToSeg.setX1(p.getX());
99  		quadraticToSeg.setY1(p.getY());
100 		update(hs);
101 	}
102 	@Override
103 	public Element getCp2() {
104 		return getCp1();
105 	}
106 	@Override
107 	public void setCp2(OMSVGPoint p, float hs) {
108 		setCp1(p, hs);
109 	}
110 
111 	@Override
112 	public void update(float hs) {
113 		float x = quadraticToSeg.getX();
114 		float y = quadraticToSeg.getY();
115 		vertex.getX().getBaseVal().setValue(x - hs);
116 		vertex.getY().getBaseVal().setValue(y - hs);
117 		vertex.getWidth().getBaseVal().setValue(hs * 2);
118 		vertex.getHeight().getBaseVal().setValue(hs * 2);
119 		if (owner.getMode() == Mode.TANGENT) {
120 			float px = previous != null ? previous.getX() : 0;
121 			float py = previous != null ? previous.getY() : 0;
122 			float x1 = quadraticToSeg.getX1();
123 			float y1 = quadraticToSeg.getY1();
124 			
125 			tg1.getX1().getBaseVal().setValue(px);
126 			tg1.getY1().getBaseVal().setValue(py);
127 			tg1.getX2().getBaseVal().setValue(x1);
128 			tg1.getY2().getBaseVal().setValue(y1);
129 			
130 			tg2.getX1().getBaseVal().setValue(x);
131 			tg2.getY1().getBaseVal().setValue(y);
132 			tg2.getX2().getBaseVal().setValue(x1);
133 			tg2.getY2().getBaseVal().setValue(y1);
134 			
135 			cp.getCx().getBaseVal().setValue(x1);
136 			cp.getCy().getBaseVal().setValue(y1);
137 			cp.getR().getBaseVal().setValue(hs);
138 		}
139 	}
140 
141 	@Override
142 	public void updateStart(OMSVGPoint delta, float hs) {
143 		quadraticToSeg.setX1(quadraticToSeg.getX1() + delta.getX());
144 		quadraticToSeg.setY1(quadraticToSeg.getY1() + delta.getY());
145 		update(hs);
146 	}
147 	
148 	@Override
149 	public void updateEnd(OMSVGPoint delta, float hs) {
150 		quadraticToSeg.setX(quadraticToSeg.getX() + delta.getX());
151 		quadraticToSeg.setY(quadraticToSeg.getY() + delta.getY());
152 		quadraticToSeg.setX1(quadraticToSeg.getX1() + delta.getX());
153 		quadraticToSeg.setY1(quadraticToSeg.getY1() + delta.getY());
154 		update(hs);
155 	}
156 
157 	@Override
158 	public void processMouseMove(OMSVGPoint delta, Element target, float hs, boolean isCtrlKeyDown) {
159 		if (target == null) {
160 			updateEnd(delta, hs);
161 			if (next != null) {
162 				next.updateStart(delta, hs);
163 			}
164 		} else if (tg2.getElement() == target) {
165 			updateEnd(delta, hs);
166 			if (next != null) {
167 				next.updateStart(delta, hs);
168 			}
169 		} else if (tg1.getElement() == target) {
170 			updateStart(delta, hs);
171 			if (previous != null) {
172 				previous.updateEnd(delta, hs);
173 			}
174 		} else if (cp.getElement() == target) {
175 			SVGSegRep prevSeg = getPreviousSplineSeg();
176 			SVGSegRep nextSeg = getNextSplineSeg();
177 			Float anglePrev = null;
178 			Float angleNext = null;
179 			if (isCtrlKeyDown) {
180 				if (prevSeg != null) {
181 					// Compute the angle between the tangent and the updated tangent
182 					OMSVGPoint v1 = owner.getSvg().createSVGPoint(
183 							quadraticToSeg.getX1() - prevSeg.getX(),
184 							quadraticToSeg.getY1() - prevSeg.getY());
185 					OMSVGPoint v2 = owner.getSvg().createSVGPoint(
186 							quadraticToSeg.getX1() + delta.getX() - prevSeg.getX(),
187 							quadraticToSeg.getY1() + delta.getY() - prevSeg.getY());
188 					float d = v1.length() * v2.length();
189 					if (d != 0) {
190 						anglePrev = (float)(Math.acos(v1.dotProduct(v2) / d) * 180 / Math.PI);						
191 						if (v1.crossProduct(v2) < 0) {
192 							anglePrev = 360 - anglePrev;
193 						}
194 					}
195 				}
196 				if (nextSeg != null) {
197 					// Compute the angle between the tangent and the updated tangent
198 					OMSVGPoint v1 = owner.getSvg().createSVGPoint(
199 							quadraticToSeg.getX1() - quadraticToSeg.getX(),
200 							quadraticToSeg.getY1() - quadraticToSeg.getY());
201 					OMSVGPoint v2 = owner.getSvg().createSVGPoint(
202 							quadraticToSeg.getX1() + delta.getX() - quadraticToSeg.getX(),
203 							quadraticToSeg.getY1() + delta.getY() - quadraticToSeg.getY());
204 					float d = v1.length() * v2.length();
205 					if (d != 0) {
206 						angleNext = (float)(Math.acos(v1.dotProduct(v2) / d) * 180 / Math.PI);						
207 						if (v1.crossProduct(v2) < 0) {
208 							angleNext = 360 - angleNext;
209 						}
210 					}					
211 				}
212 			}
213 			quadraticToSeg.setX1(quadraticToSeg.getX1() + delta.getX());
214 			quadraticToSeg.setY1(quadraticToSeg.getY1() + delta.getY());
215 			update(hs);
216 			if (anglePrev != null) {
217 				// Apply the same rotation to the spline cubic tangent
218 				OMSVGMatrix m = owner.getSvg().createSVGMatrix();
219 				m = m.translate(prevSeg.getX(), prevSeg.getY());
220 				m = m.rotate(anglePrev);
221 				m = m.translate(-prevSeg.getX(), -prevSeg.getY());
222 				OMSVGPoint p0 = owner.getSvg().createSVGPoint(
223 						prevSeg.getX2(),
224 						prevSeg.getY2());
225 				OMSVGPoint p1 = p0.matrixTransform(m).substract(p0);
226 				prevSeg.processMouseMove(p1, prevSeg.getCp2(), hs, false);
227 			}
228 			if (angleNext != null) {
229 				// Apply the same rotation to the next spline tangent
230 				OMSVGMatrix m = owner.getSvg().createSVGMatrix();
231 				m = m.translate(quadraticToSeg.getX(), quadraticToSeg.getY());
232 				m = m.rotate(angleNext);
233 				m = m.translate(-quadraticToSeg.getX(), -quadraticToSeg.getY());
234 				OMSVGPoint p0 = owner.getSvg().createSVGPoint(
235 						nextSeg.getX1(),
236 						nextSeg.getY1());
237 				OMSVGPoint p1 = p0.matrixTransform(m).substract(p0);
238 				nextSeg.processMouseMove(p1, nextSeg.getCp1(), hs, false);
239 			}
240 		}
241 	}
242 	
243 	@Override
244 	public String toString() {
245 		StringBuilder builder = new StringBuilder("Q ");
246 		builder.append(quadraticToSeg.getX1());
247 		builder.append(",");
248 		builder.append(quadraticToSeg.getY1());
249 		builder.append(" ");
250 		builder.append(quadraticToSeg.getX());
251 		builder.append(",");
252 		builder.append(quadraticToSeg.getY());
253 		return builder.toString();
254 	}
255 
256 }