Add an option to display areas of closed contours.

This is useful e.g. for architectural work.
This commit is contained in:
EvilSpirit 2017-03-30 21:39:42 +07:00 committed by whitequark
parent c0b6eaa935
commit 99f6ea34f1
14 changed files with 82 additions and 0 deletions

View File

@ -49,6 +49,7 @@ New measurement/analysis features:
"Analyze → Measure Perimeter".
* New command for measuring center of mass, with live updates as the sketch
changes, "Analyze → Center of Mass".
* New option for displaying areas of closed contours.
* When selecting a point and a line, projected distance to to current
workplane is displayed.

View File

@ -84,6 +84,11 @@ void TextWindow::ScreenChangeBackFaces(int link, uint32_t v) {
InvalidateGraphics();
}
void TextWindow::ScreenChangeShowContourAreas(int link, uint32_t v) {
SS.showContourAreas = !SS.showContourAreas;
InvalidateGraphics();
}
void TextWindow::ScreenChangeCheckClosedContour(int link, uint32_t v) {
SS.checkClosedContour = !SS.checkClosedContour;
InvalidateGraphics();
@ -297,6 +302,9 @@ void TextWindow::ShowConfiguration() {
Printf(false, " %Fd%f%Ll%s check sketch for closed contour%E",
&ScreenChangeCheckClosedContour,
SS.checkClosedContour ? CHECK_TRUE : CHECK_FALSE);
Printf(false, " %Fd%f%Ll%s show areas of closed contours%E",
&ScreenChangeShowContourAreas,
SS.showContourAreas ? CHECK_TRUE : CHECK_FALSE);
Printf(false, "");
Printf(false, "%Ft autosave interval (in minutes)%E");

View File

@ -693,6 +693,16 @@ void GraphicsWindow::Draw(Canvas *canvas) {
c.Draw(Constraint::DrawAs::DEFAULT, canvas);
}
// Draw areas
if(SS.showContourAreas) {
for(hGroup hg : SK.groupOrder) {
Group *g = SK.GetGroup(hg);
if(g->h.v != activeGroup.v) continue;
if(!(g->IsVisible())) continue;
g->DrawContourAreaLabels(canvas);
}
}
// Draw the "pending" constraint, i.e. a constraint that would be
// placed on a line that is almost horizontal or vertical.
if(SS.GW.pending.operation == Pending::DRAGGING_NEW_LINE_POINT &&

View File

@ -677,3 +677,38 @@ void Group::DrawFilledPaths(Canvas *canvas) {
}
}
void Group::DrawContourAreaLabels(Canvas *canvas) {
const Camera &camera = canvas->GetCamera();
Vector gr = camera.projRight.ScaledBy(1 / camera.scale);
Vector gu = camera.projUp.ScaledBy(1 / camera.scale);
for(SBezierLoopSet &sbls : bezierLoops.l) {
if(sbls.l.n == 0 || sbls.l.elem[0].l.n == 0) continue;
Vector min = sbls.l.elem[0].l.elem[0].ctrl[0];
Vector max = min;
Vector zero = Vector::From(0.0, 0.0, 0.0);
sbls.GetBoundingProjd(Vector::From(1.0, 0.0, 0.0), zero, &min.x, &max.x);
sbls.GetBoundingProjd(Vector::From(0.0, 1.0, 0.0), zero, &min.y, &max.y);
sbls.GetBoundingProjd(Vector::From(0.0, 0.0, 1.0), zero, &min.z, &max.z);
Vector mid = min.Plus(max).ScaledBy(0.5);
hStyle hs = { Style::CONSTRAINT };
Canvas::Stroke stroke = Style::Stroke(hs);
stroke.layer = Canvas::Layer::FRONT;
double scale = SS.MmPerUnit();
std::string label = ssprintf("%.3f %s²",
fabs(sbls.SignedArea() / (scale * scale)),
SS.UnitName());
double fontHeight = Style::TextHeight(hs);
double textWidth = VectorFont::Builtin()->GetWidth(fontHeight, label),
textHeight = VectorFont::Builtin()->GetCapHeight(fontHeight);
Vector pos = mid.Minus(gr.ScaledBy(textWidth / 2.0))
.Minus(gu.ScaledBy(textHeight / 2.0));
canvas->DrawVectorText(label, fontHeight, pos, gr, gu, canvas->GetStroke(stroke));
}
}

View File

@ -287,6 +287,7 @@ public:
void Draw(Canvas *canvas);
void DrawPolyError(Canvas *canvas);
void DrawFilledPaths(Canvas *canvas);
void DrawContourAreaLabels(Canvas *canvas);
SPolygon GetPolygon();

View File

@ -70,6 +70,8 @@ void SolveSpaceUI::Init() {
drawBackFaces = CnfThawBool(true, "DrawBackFaces");
// Check that contours are closed and not self-intersecting
checkClosedContour = CnfThawBool(true, "CheckClosedContour");
// Draw closed polygons areas
showContourAreas = CnfThawBool(false, "ShowContourAreas");
// Export shaded triangles in a 2d view
exportShadedTriangles = CnfThawBool(true, "ExportShadedTriangles");
// Export pwl curves (instead of exact) always
@ -191,6 +193,8 @@ void SolveSpaceUI::Exit() {
CnfFreezeBool(fixExportColors, "FixExportColors");
// Draw back faces of triangles (when mesh is leaky/self-intersecting)
CnfFreezeBool(drawBackFaces, "DrawBackFaces");
// Draw closed polygons areas
CnfFreezeBool(showContourAreas, "ShowContourAreas");
// Check that contours are closed and not self-intersecting
CnfFreezeBool(checkClosedContour, "CheckClosedContour");
// Export shaded triangles in a 2d view

View File

@ -651,6 +651,7 @@ public:
float exportOffset;
bool fixExportColors;
bool drawBackFaces;
bool showContourAreas;
bool checkClosedContour;
bool showToolbar;
Platform::Path screenshotFile;

View File

@ -536,6 +536,17 @@ void SBezierLoopSet::GetBoundingProjd(Vector u, Vector orig,
}
}
double SBezierLoopSet::SignedArea() {
if(EXACT(area == 0.0)) {
SPolygon sp = {};
MakePwlInto(&sp);
sp.normal = sp.ComputeNormal();
area = sp.SignedArea();
sp.Clear();
}
return area;
}
//-----------------------------------------------------------------------------
// Convert all the Beziers into piecewise linear form, and assemble that into
// a polygon, one contour per loop.

View File

@ -151,6 +151,7 @@ public:
List<SBezierLoop> l;
Vector normal;
Vector point;
double area;
static SBezierLoopSet From(SBezierList *spcl, SPolygon *poly,
double chordTol,
@ -158,6 +159,7 @@ public:
SBezierList *openContours);
void GetBoundingProjd(Vector u, Vector orig, double *umin, double *umax) const;
double SignedArea();
void MakePwlInto(SPolygon *sp) const;
void Clear();
};

View File

@ -517,6 +517,7 @@ public:
static void ScreenChangeFixExportColors(int link, uint32_t v);
static void ScreenChangeBackFaces(int link, uint32_t v);
static void ScreenChangeShowContourAreas(int link, uint32_t v);
static void ScreenChangeCheckClosedContour(int link, uint32_t v);
static void ScreenChangePwlCurves(int link, uint32_t v);
static void ScreenChangeCanvasSizeAuto(int link, uint32_t v);

View File

@ -11,6 +11,7 @@ endforeach()
set(testsuite_SOURCES
harness.cpp
analysis/contour_area/test.cpp
core/expr/test.cpp
core/locale/test.cpp
core/path/test.cpp

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

View File

@ -0,0 +1,7 @@
#include "harness.h"
TEST_CASE(normal_roundtrip) {
SS.showContourAreas = true;
CHECK_LOAD("normal.slvs");
CHECK_RENDER("normal.png");
}