[qet] [2760] DXF Arc & Ellipse: Improved approximate formation.

[ Thread Index | Date Index | More lists.tuxfamily.org/qet Archives ]


Revision: 2760
Author:   abhishekm71
Date:     2014-01-20 12:46:34 +0100 (Mon, 20 Jan 2014)
Log Message:
-----------
DXF Arc & Ellipse: Improved approximate formation.
The ellipse is divided into 4 parts (as per 4 quadrants). 
These 4 arcs are drawn separately by approximating them as arcs of circles.

Modified Paths:
--------------
    trunk/sources/exportdialog.cpp

Modified: trunk/sources/exportdialog.cpp
===================================================================
--- trunk/sources/exportdialog.cpp	2014-01-20 02:39:14 UTC (rev 2759)
+++ trunk/sources/exportdialog.cpp	2014-01-20 11:46:34 UTC (rev 2760)
@@ -441,9 +441,9 @@
 					y -= fontSize*1.06;
 				else if (int(angle - 180) % 360 == 0) // 180 degrees rotation
 					y += fontSize*1.06;
-				else if (int(angle - 270) % 360 == 0) // 90 degrees rotation
+				else if (int(angle - 270) % 360 == 0) // 270 degrees rotation
 					x -= fontSize*1.06;
-				else // ((angle - 90) % 360 == 0)  270 degrees rotation
+				else // ((angle - 90) % 360 == 0)  90 degrees rotation
 					x += fontSize*1.06;
 			}
 
@@ -579,9 +579,9 @@
 					y -= fontSize*1.06;
 				else if (int(angle - 180) % 360 == 0) // 180 degrees rotation
 					y += fontSize*1.06;
-				else if (int(angle - 270) % 360 == 0) // 90 degrees rotation
+				else if (int(angle - 270) % 360 == 0) // 270 degrees rotation
 					x -= fontSize*1.06;
-				else // ((angle - 90) % 360 == 0)  270 degrees rotation
+				else // ((angle - 90) % 360 == 0)  90 degrees rotation
 					x += fontSize*1.06;
 			}
 
@@ -608,9 +608,9 @@
 				y -= fontSize*1.06;
 			else if (int(angle - 180) % 360 == 0) // 180 degrees rotation
 				y += fontSize*1.06;
-			else if (int(angle - 270) % 360 == 0) // 90 degrees rotation
+			else if (int(angle - 270) % 360 == 0) // 270 degrees rotation
 				x -= fontSize*1.06;
-			else // ((angle - 90) % 360 == 0)  270 degrees rotation
+			else // ((angle - 90) % 360 == 0)  90 degrees rotation
 				x += fontSize*1.06;
 		}
 	}
@@ -621,28 +621,126 @@
 void ExportDialog::drawDxfArcEllipse(QString file_path, qreal x, qreal y, qreal w, qreal h, qreal startAngle,
 									 qreal spanAngle, qreal hotspot_x, qreal hotspot_y, qreal rotation_angle) {
 
-	/*//if horizontal ellipse
-	if (w > h) {
-		qreal sin1 = sin(startAngle);
-		qreal sin2 = sin(startAngle + spanAngle);
-		if (sin1 > 0 && sin2 < 0) {
+	// vector of parts of arc (stored as a pair of startAngle and spanAngle) for each quadrant.
+	QVector< QPair<qreal,qreal> > arc_parts_vector;
 
+	if (spanAngle > 0) {
+		qreal start = startAngle;
+		qreal span;
+		int i;
+		for ( i = startAngle; i < startAngle+spanAngle; i++ ) {
+			int absolute_theta = (i > 0) ? i : -i;
+			if (absolute_theta == 0 || absolute_theta == 90 ||
+				absolute_theta == 180 || absolute_theta == 270 ||
+				absolute_theta == 360) {
+				span = i - start;
+				QPair<qreal, qreal> newPart(start,span);
+				arc_parts_vector.push_back(newPart);
+				start = i;
+			}
 		}
-	}*/
-	qreal center_x = x + w/2;
-	qreal center_y = y - w/2;
-	qreal radius = (w+h)/4;
-	qreal endAngle = startAngle + spanAngle;
-	QPointF transformed_point = rotation_transformed(center_x, center_y, hotspot_x, hotspot_y, rotation_angle);
-	center_x = transformed_point.x();
-	center_y = transformed_point.y();
-	if (startAngle == 0 && spanAngle == 360)
-		Createdxf::drawCircle(file_path, radius, center_x, center_y, 0);
-	else {
-		endAngle += rotation_angle;
-		startAngle += rotation_angle;
-		Createdxf::drawArc(file_path, center_x, center_y, radius, endAngle, startAngle, 0);
+		if (start != i) {
+			span = i - start;
+			QPair<qreal, qreal> newPart(start,span);
+			arc_parts_vector.push_back(newPart);
+		}
+	} else {
+		qreal start = startAngle;
+		qreal span;
+		int i;
+		for ( i = startAngle; i > startAngle+spanAngle; i-- ) {
+			int absolute_theta = (i > 0) ? i : -i;
+			if (absolute_theta == 0 || absolute_theta == 90 ||
+				absolute_theta == 180 || absolute_theta == 270 ||
+				absolute_theta == 360) {
+				span = i - start;
+				QPair<qreal, qreal> newPart(start,span);
+				arc_parts_vector.push_back(newPart);
+				start = i;
+			}
+		}
+		if (start != i) {
+			span = i - start;
+			QPair<qreal, qreal> newPart(start,span);
+			arc_parts_vector.push_back(newPart);
+		}
 	}
+
+	for (int i = 0; i < arc_parts_vector.size(); i++) {
+
+		QPair<qreal,qreal> arc = arc_parts_vector[i];
+		if (arc.second == 0)
+			continue;
+		qreal arc_startAngle = arc.first * 3.142/180;
+		qreal arc_spanAngle = arc.second * 3.142/180;
+
+		qreal a = w/2;
+		qreal b = h/2;
+
+		qreal x1 = x + w/2 + a*cos(arc_startAngle);
+		qreal y1 = y - h/2 + b*sin(arc_startAngle);
+		qreal x2 = x + w/2 + a*cos(arc_startAngle + arc_spanAngle);
+		qreal y2 = y - h/2 + b*sin(arc_startAngle + arc_spanAngle);
+
+
+		qreal mid_ellipse_x = x + w/2 + a*cos(arc_startAngle + arc_spanAngle/2);
+		qreal mid_ellipse_y = y - h/2 + b*sin(arc_startAngle + arc_spanAngle/2);
+		qreal mid_line_x = (x1+x2)/2;
+		qreal mid_line_y = (y1+y2)/2;
+
+		qreal x3 = (mid_ellipse_x + mid_line_x)/2;
+		qreal y3 = (mid_ellipse_y + mid_line_y)/2;
+
+		// find circumcenter of points (x1,y1), (x3,y3) and (x2,y2)
+		qreal a1 = 2*x2 - 2*x1;
+		qreal b1 = 2*y2 - 2*y1;
+		qreal c1 = x1*x1 + y1*y1 - x2*x2 - y2*y2;
+
+		qreal a2 = 2*x3 - 2*x1;
+		qreal b2 = 2*y3 - 2*y1;
+		qreal c2 = x1*x1 + y1*y1 - x3*x3 - y3*y3;
+
+		qreal center_x = (b1*c2 - b2*c1) / (a1*b2 - a2*b1);
+		qreal center_y = (a1*c2 - a2*c1) / (b1*a2 - b2*a1);
+
+		qreal radius = sqrt( (x1-center_x)*(x1-center_x) + (y1-center_y)*(y1-center_y) );
+
+		if ( x1 > center_x && y1 > center_y )
+			arc_startAngle = asin( (y1 - center_y) / radius );
+		else if ( x1 > center_x && y1 < center_y )
+			arc_startAngle = 3.142*2 - asin( (center_y - y1) / radius );
+		else if ( x1 < center_x && y1 < center_y )
+			arc_startAngle = 3.142 + asin( (center_y - y1) / radius );
+		else
+			arc_startAngle = 3.142 - asin( (y1 - center_y) / radius );
+
+		qreal arc_endAngle;
+
+		if ( x2 > center_x && y2 > center_y )
+			arc_endAngle = asin( (y2 - center_y) / radius );
+		else if ( x2 > center_x && y2 < center_y )
+			arc_endAngle = 3.142*2 - asin( (center_y - y2) / radius );
+		else if ( x2 < center_x && y2 < center_y )
+			arc_endAngle = 3.142 + asin( (center_y - y2) / radius );
+		else
+			arc_endAngle = 3.142 - asin( (y2 - center_y) / radius );
+
+		if (arc_endAngle < arc_startAngle) {
+			qreal temp = arc_startAngle;
+			arc_startAngle = arc_endAngle;
+			arc_endAngle = temp;
+		}
+
+		QPointF transformed_point = rotation_transformed(center_x, center_y, hotspot_x, hotspot_y, rotation_angle);
+		center_x = transformed_point.x();
+		center_y = transformed_point.y();
+		arc_endAngle *= 180/3.142;
+		arc_startAngle *= 180/3.142;
+		arc_endAngle -= rotation_angle;
+		arc_startAngle -= rotation_angle;
+
+		Createdxf::drawArc(file_path, center_x, center_y, radius, arc_startAngle, arc_endAngle, 0);
+	}
 }
 
 QPointF ExportDialog::rotation_transformed(qreal px, qreal py , qreal origin_x, qreal origin_y, qreal angle) {


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/