/* MetaContour, version 0.1 -------------------------------------- */ /* Copyright(C) 2004, Brooks Moses */ /* */ /* This version of MetaContour is made available under the Gnu */ /* Public License; see metacontour_main.cc for details. */ /* */ /* This is a very pre-release version of MetaContour, distributed */ /* primarily as an example of a use of MetaPlot. It can be */ /* compiled with gcc using the line: */ /* */ /* g++ metacontour.cc cpoint.cc metacontour_main.cc */ /* */ /*-----------------------------------------------------------------*/ #include"metacontour.h" using namespace std; MetapostContours::MetapostContours(cparray& PlotData, vector& ContourListIn, string& PlotNameIn) { ContourList = ContourListIn; PlotName = PlotNameIn; GridCommand = "addto " + PlotName + ".Grid doublepath "; DrawCommand = "addto " + PlotName + ".LinePlot doublepath "; FillCommand = "addto " + PlotName + ".FillPlot contour "; GridStream << "picture " << PlotName << ".Grid; " << PlotName << ".Grid := nullpicture;\n"; LinePlotStream << "picture " << PlotName << ".LinePlot; " << PlotName << ".LinePlot := nullpicture;\n"; FillPlotStream << "picture " << PlotName << ".FillPlot; " << PlotName << ".FillPlot := nullpicture;\n"; /* Construct contours */ cpoint x00; cpoint x01; cpoint x10; cpoint x11; for (int j=1; j= ContourList.size()) return; double zc2 = ContourList[contourLevel]; if (x1.z > zc2) { /* another corner */ cpoint y1 = x4.interpolateto(x1, zc2); cpoint y2 = x2.interpolateto(x1, zc2); DrawFilled(contourLevel, y1, y2, x1); DrawLine(contourLevel, y1, y2); PlotCorner(x1, x2, x3, x4, contourLevel+1); } } /* Continue plotting for a two-corner side of a grid square */ // // Search Region: x3--------x2 // |.....ooooo| // |.....ooooo| // |.....ooooo| // |.....ooooo| // x4--------x1 // void MetapostContours::PlotRect(cpoint x1, cpoint x2, cpoint x3, cpoint x4, int contourLevel) { if (contourLevel >= ContourList.size()) return; double zc2 = ContourList[contourLevel]; if (x1.z > zc2) { if (x2.z > zc2) { /* another rectangle */ cpoint y1 = x4.interpolateto(x1, zc2); cpoint y2 = x3.interpolateto(x2, zc2); DrawFilled(contourLevel, y1, y2, x2, x1); DrawLine(contourLevel, y1, y2); PlotRect(x1, x2, x3, x4, contourLevel+1); } else { /* corner around x1 */ cpoint y1 = x4.interpolateto(x1, zc2); cpoint y2 = x2.interpolateto(x1, zc2); DrawFilled(contourLevel, y1, y2, x1); DrawLine(contourLevel, y1, y2); PlotCorner(x1, x2, x3, x4, contourLevel+1); } } else { if (x2.z > zc2) { /* corner around x2 */ cpoint y1 = x1.interpolateto(x2, zc2); cpoint y2 = x3.interpolateto(x2, zc2); DrawFilled(contourLevel, y1, y2, x2); DrawLine(contourLevel, y1, y2); PlotCorner(x2, x3, x4, x1, contourLevel+1); } } } /* Continue plotting for a three-corner pentagon of a grid square */ // // Search Region: x3--------x2 // |oooooooooo| // |..oooooooo| // |....oooooo| // |......oooo| // x4--------x1 // void MetapostContours::PlotPent(cpoint x1, cpoint x2, cpoint x3, cpoint x4, int contourLevel) { if (contourLevel >= ContourList.size()) return; double zc2 = ContourList[contourLevel]; if (x1.z > zc2) { if (x3.z > zc2) { if (x2.z < zc2) { /* a saddle-point hexagon, or two corners */ cpoint y1 = x4.interpolateto(x1, zc2); cpoint y2 = x2.interpolateto(x1, zc2); cpoint y3 = x2.interpolateto(x3, zc2); cpoint y4 = x4.interpolateto(x3, zc2); double zcenter = cpoint::saddlepoint(x1, x2, x3, x4); if (zcenter < zc2) { /* two corners around x1 and x3 */ DrawFilled(contourLevel, y1, y2, x1); DrawLine(contourLevel, y1, y2); PlotCorner(x1, x2, x3, x4, contourLevel+1); DrawFilled(contourLevel, y3, y4, x3); DrawLine(contourLevel, y3, y4); PlotCorner(x3, x4, x1, x2, contourLevel+1); } else { /* a saddle-point hexagon */ DrawFilled(contourLevel, y1, y4, x3, y3, y2, x1); DrawLine(contourLevel, y1, y4); DrawLine(contourLevel, y3, y2); PlotHex(x1, x2, x3, x4, contourLevel+1, zcenter); } } else { /* another pentagon */ cpoint y1 = x4.interpolateto(x1, zc2); cpoint y2 = x4.interpolateto(x3, zc2); DrawFilled(contourLevel, y1, y2, x3, x2, x1); DrawLine(contourLevel, y1, y2); PlotPent(x1, x2, x3, x4, contourLevel+1); } } else { // (x3.z < zc2) if (x2.z > zc2) { /* rectangle around x1, x2 */ cpoint y1 = x4.interpolateto(x1, zc2); cpoint y2 = x3.interpolateto(x2, zc2); DrawFilled(contourLevel, y1, y2, x2, x1); DrawLine(contourLevel, y1, y2); PlotRect(x1, x2, x3, x4, contourLevel+1); } else { /* corner around x1 */ cpoint y1 = x4.interpolateto(x1, zc2); cpoint y2 = x2.interpolateto(x1, zc2); DrawFilled(contourLevel, y1, y2, x1); DrawLine(contourLevel, y1, y2); PlotCorner(x1, x2, x3, x4, contourLevel+1); } } } else { // (x1.z < zc2) if (x3.z > zc2) { if (x2.z > zc2) { /* rectangle around x2, x3 */ cpoint y1 = x1.interpolateto(x2, zc2); cpoint y2 = x4.interpolateto(x3, zc2); DrawFilled(contourLevel, y1, y2, x3, x2); DrawLine(contourLevel, y1, y2); PlotRect(x2, x3, x4, y1, contourLevel+1); } else { /* corner around x3 */ cpoint y1 = x2.interpolateto(x3, zc2); cpoint y2 = x4.interpolateto(x3, zc2); DrawFilled(contourLevel, y1, y2, x3); DrawLine(contourLevel, y1, y2); PlotCorner(x3, x4, x1, x2, contourLevel+1); } } else { if (x2.z > zc2) { /* corner around x2 */ cpoint y1 = x1.interpolateto(x2, zc2); cpoint y2 = x3.interpolateto(x2, zc2); DrawFilled(contourLevel, y1, y2, x2); DrawLine(contourLevel, y1, y2); PlotCorner(x2, x3, x4, x1, contourLevel+1); } } } } /* Continue plotting for a two-corner hex in a grid square */ // // Search Region: x3--------x2 // |oooooo....| // |oooooooo..| // |..oooooooo| // |....oooooo| // x4--------x1 // void MetapostContours::PlotHex(cpoint x1, cpoint x2, cpoint x3, cpoint x4, int contourLevel, double zcenter) { if (contourLevel >= ContourList.size()) return; double zc2 = ContourList[contourLevel]; if (x1.z > zc2) { if (x3.z > zc2) { /* another saddle-point hexagon, or two corners */ cpoint y1 = x4.interpolateto(x1, zc2); cpoint y2 = x2.interpolateto(x1, zc2); cpoint y3 = x2.interpolateto(x3, zc2); cpoint y4 = x4.interpolateto(x3, zc2); if (zcenter < zc2) { /* two corners around x1 and x3 */ DrawFilled(contourLevel, y1, y2, x1); DrawLine(contourLevel, y1, y2); PlotCorner(x1, x2, x3, x4, contourLevel+1); DrawFilled(contourLevel, y3, y4, x3); DrawLine(contourLevel, y3, y4); PlotCorner(x3, x4, x1, x2, contourLevel+1); } else { /* another saddle-point hexagon */ DrawFilled(contourLevel, y1, y4, x3, y3, y2, x1); DrawLine(contourLevel, y1, y4); DrawLine(contourLevel, y3, y2); PlotHex(x1, x2, x3, x4, contourLevel+1, zcenter); } } else { /* corner around x1 */ cpoint y1 = x4.interpolateto(x1, zc2); cpoint y2 = x2.interpolateto(x1, zc2); DrawFilled(contourLevel, y1, y2, x1); DrawLine(contourLevel, y1, y2); PlotCorner(x1, x2, x3, x4, contourLevel+1); } } else { if (x3.z > zc2) { /* corner around x3 */ cpoint y1 = x2.interpolateto(x3, zc2); cpoint y2 = x4.interpolateto(x3, zc2); DrawFilled(contourLevel, y1, y2, x2); DrawLine(contourLevel, y1, y2); PlotCorner(x3, x4, x1, x2, contourLevel+1); } } } void MetapostContours::DrawGrid (cpoint x1, cpoint x2) { GridStream << GridCommand << x1.metapoint() << "--" << x2.metapoint() << ";\n"; } void MetapostContours::DrawLine (int contourLevel, cpoint x1, cpoint x2) { LinePlotStream << DrawCommand << x1.metapoint() << "--" << x2.metapoint() << " withcolor contourcolor" << contourLevel+1 << ";\n"; } void MetapostContours::DrawFilled (int contourLevel, cpoint x1, cpoint x2, cpoint x3) { FillPlotStream << FillCommand << x1.metapoint() << "--" << x2.metapoint() << "--" << x3.metapoint() << "--cycle withcolor contourcolor" << contourLevel+1 << ";\n"; } void MetapostContours::DrawFilled (int contourLevel, cpoint x1, cpoint x2, cpoint x3, cpoint x4) { FillPlotStream << FillCommand << x1.metapoint() << "--" << x2.metapoint() << "--" << x3.metapoint() << "--" << x4.metapoint() << "--cycle withcolor contourcolor" << contourLevel+1 << ";\n"; } void MetapostContours::DrawFilled (int contourLevel, cpoint x1, cpoint x2, cpoint x3, cpoint x4, cpoint x5) { FillPlotStream << FillCommand << x1.metapoint() << "--" << x2.metapoint() << "--" << x3.metapoint() << "--" << x4.metapoint() << "--" << x5.metapoint() << "--cycle withcolor contourcolor" << contourLevel+1 << ";\n"; } void MetapostContours::DrawFilled (int contourLevel, cpoint x1, cpoint x2, cpoint x3, cpoint x4, cpoint x5, cpoint x6) { FillPlotStream << FillCommand << x1.metapoint() << "--" << x2.metapoint() << "--" << x3.metapoint() << "--" << x4.metapoint() << "--" << x5.metapoint() << "--" << x6.metapoint() << "--cycle withcolor contourcolor" << contourLevel+1 << ";\n"; }