Skip to Content.
Sympa Menu

cgal-discuss - Re: [cgal-discuss] Polygon adding circular arc work in some cases but not always

Subject: CGAL users discussion list

List archive

Re: [cgal-discuss] Polygon adding circular arc work in some cases but not always


Chronological Thread 
  • From: Nicklas SB Karlsson <>
  • To:
  • Subject: Re: [cgal-discuss] Polygon adding circular arc work in some cases but not always
  • Date: Sat, 25 Nov 2023 20:25:05 +0100
  • Authentication-results: mail3-smtp-sop.national.inria.fr; spf=None ; spf=Pass ; spf=Pass
  • Ironport-data: A9a23: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
  • Ironport-hdrordr: A9a23:ZMRxxav0lWIo8SWh6aKq1jEI7skDcdV00zEX/kB9WHVpm62j5q KTdZEgvyMc5wxxZJhNo7+90ey7IU80lqQFhbX5X43OYOCOggLBR72Kr7GSoAEIcBeTygcy78 ldmuRFebjNJGk/o+HWpDOxCdNI+qjhzJyV
  • Ironport-phdr: A9a23:h+boQx2ePF4WzTJosmDOCQ8yDhhOgF0UFjAc5pdvsb9SaKPrp82kY BaPo6ww0xSQB96TwskHotSVmpijY1BI2YyGvnEGfc4EfD4+ouJSoTYdBtWYA1bwNv/gYn9yN s1DUFh44yPzahANS47xaFLIv3K98yMZFAnhOgppPOT1HZPZg9iq2+yo9JDffQZFiCCgbb5yL hi6ohjdutcYjIB/Nqs/1xzFr2dHdOhR2W5mP1WfkQri6Myt5pBj6SNQu/wg985ET6r3erkzQ KJbAjo7LW07/dXnuhbfQwSB4HscSXgWnQFTAwfZ9hH6X4z+vTX8u+FgxSSVJ8z2TbQzWTS/8 6dmTQLjhSkbOzIl9mzcl8p9h79Zrh28vRxy243abpyVOvRgcK3Sf90aSnZPUcleTCFBB5+wY pEVAuYdJ+tVrY/wrEYOoxukAgmsAfvixCdJhnDq3q061/4uERrb1wI9At8FrXHao8/vNKcWS uC1167IzTPeZP5R3zf965PFchYiofGXRr18a9TeyVQ2Gg7Dk16fppDrMSmP2eQRr2iU8fBgV eS3hmI7twx8oTyiyMcyhoTUmI4YyF/K+CdlzIg6KtO1S0F2b9CmHZZUuS+WK4h7T94tTm9nv Cs3y78Lt5C0cSYFyJkqwQPUZf+fc4WQ/B7vSeScLS16iX55Yr6zmhW//Ea6xuHhUsS50VBHp Tdbn9nIq3ANzADT5dadSvVg/0eg2CiA2hjP5uxCPEs6j7DUK4Q7zb41jpcTsVrMHivxmEjul q+ZaEEk9fKo6unoe7npu4WQN4puhQH/NqQigMO/Dv4+MgcTXmiX4+K826P//UHhQbVKiOM5k rXBvZzEOMgWpLS1Dg1J3oo59hqyDDmr3M4FkXQDLV9JYBeHgJLoO1HKLvD4F/C/g1G0nTdtx PDLJbvhApbWLnfYirvuY6t951ZayAUo1d9f/Y5bCqkdIPLvXU/8rMHUAgcjMwOo2+bnFMl91 oQGVG2TDa+WKqfSvUaV6eIuOOmDeJIVuC3mK/U+/P7vjXo5mUcHcqWz3JsXbmq4HvV8LEmDb 3rsmIRJLWBftQU3SKnmiUaJTCVIT3e0RaM1oD8hW6y8CoKWYIGmg7iIx2+ANNV1b3pCEUuLF z+8cYasXfQXYmSfP5kywXQ/SbG9Rtp5hlmVvwjgxu8/RgK10igRtJa4kcNw+/WWjhYqszp9E 8Wa1WiJCWByhGIBATEsj+hkuUIo7FCF3OBjhuBAU8RJ7qZPUS88NoXWieFnWJjpQgyURt6SU x69R8m+RzQ4T9Y/2dgLNkB+M9OhlRqF0jf5S6QNmemzDYcvurnZw2C3J8t5zCPe07I9ilA9X sZVHXergqduq03fQYvAkkHfmK+seaVa2iPRnIua5UyJukwQEAt5UKGeGGsaelOTttPhoEXLU 76pD70jdApH08+LbKVQOJXvih1dSfHvNc67ASr5knqsBRuO2rKHbZb7M2Qb0iLHDUEYkgcVt X+YPAk6Dy2lrirQFjtrXV7oZkrt96F5pju9TWcyzBqAKUB8lt/XslYUifGaV/IPz+ccoi5y4 z5wHVu7w5fXE4/a/lUnI/0aOINmpg4WizG81UQ1JJGrIqF8i0RLdg12uxirzBBrEsBbltBsq no2zQ10IKbe0VVbdjre04qjX9+fYmT04h2rbLbbn1/E19PDsKEMwPI7sF+lsRzjRQIytm5q1 dVYyS7W4JbiCgkJW9T8Twxkknoy76GfaS476YTO0HRqOqThqT7O1eUiA+49wwqhddNSWE+dP Df7CNZSR82nKehx3kOscgpBJ+dKsqg9I8KhcfKCnq+tJudp2jy83yxL54V000TE8CQZKKaA2 ZUtxfKD1E2KSn/wgUygvcb+hY1fLWtLQSzgkW69VNUXP/wsNY8QQX+jOci22slzi9b2VnhU+ UTiYjFOkM6ldByObkDsiAhZ1EAZu3uiymOzyz15lS1sr7LKhnWRhbu6MkNXYSgSFTcx6DWka ZK5hN0bQkWyOg0glR/+oF3/27Aev6NnaW/aXUZPeSHyaWBkSKq58LSYMKstoNsltztaVOOkb BWUULn49lEc0AvlHHBUgj0mPWLiqtDikhp2hXjIZnBwhHzaYss2yAqVt7m+DbZBmzEBQid/k zzeAFOxasKo8dujnJDGqumiVmilW84bYWzxwIiHrif++XxyDEj1gaWogtO+W1tfs2ezx5xwW C7Pthq5foT7y/HwL7d8ZkcxTF7kt5ggQ944zdN23c5AnyFL3NLPox9l2S/yKYsJg/qmNShRT 29bkdLevFq1ih8kcC7BxpqlBC/EnY0+P5/jMjhQg3NnqJoabcXcpL1cwXkv+wX+8lqXOKgn2 GhHjqB0oH8C37NT4VVrkX3bW+BIWxYEene230OB69T0xElOTF6maqP4lE93nNT6SaqHvhkZQ 3HhPJErAS536Mx7dlPKynz6rI/+KpHcatcatxvclBml7aAdMJUqiv8DnjZqI0rnsHks2rJ+g Vpr1JC++oeOLWlsuqS0HlZUOyb0aMUa5jz2xfwHwYDJh8b2Ts4nQ2RVOfmgBfuzWCofr/HmK xqDHHUnp3GXFKCeVQ6T5UF6rm7eRpCmM3bEbHIdzNhkWFycPBkF2V9SA218x85iUFn7mp+EE g8x/D0a61/mpwEZz+tpM0K6SWLDvEKzbS9yTpGDLR1Q5wUE5kHPMMXY4PggekMQtpCnsgGJL XSWIgpSCmRcEEqHL1bgJbPo6MSKoI36TqKuauDDZ7mDs7kUT/CT2ZemyZdr5R6WO8GGLyUnA 7s+00tHG39wHcjY3TMCV2ZE8kCFJ97erxC69Cptq8m5+/m+QwPj67yEDL5KOMlu8RS70u+Tc vSdjyFjJXNEx4sBkDXWnaMH0gdY2EQMP3G9VK4NvinXQOfMl79LWlQFPjhrOpIA5up51w1Jc 6Yzb/vz1aVyyPMoWQ8tvbPJnMKyb4oHPjPkXLsmLFyGML2XeXjHhcT+YKf6RrRWgOQSsRCs6 2/zLg==
  • Ironport-sdr: 65624a17_OvWbXkWx0ThKHKNPrgxZINOIfJeY6KgZXigHfXXQRzjJQgt zX47Te2NuMi3LbUaoCAVKzLwj+ncWmsZ3Mxz50g==

Attached as a .zip file.

Or if your prefer also as separate files. CMakeLists.txt in top directory, src_CmakeLists.txt renamed to CMakeLists.txt put into src subdirectory, main.cpp put in src subdirectory, ConstantToolEngagementAngle.cbp Codeblocks project file put into subdirectory maybe with name ConstantToolEngagementAngle.

Make subdirectory build if needed and change to this directory. Run cmake .. and then run make and then there should be a executable built into the build directory.


Regards Nicklas  Karlsson


lör 2023-11-25 klockan 10:53 +0200 skrev Efi Fogel:
Please provide a complete stand-alone example that compiles.
   ____  _        ____             _
  /_____/_) o    /__________  __  //
 (____ (   (    (    (_/ (_/-(-'_(/
                         _/




On Fri, 24 Nov 2023 at 23:44, Nicklas SB Karlsson <> wrote:
Have been able to make polygons with connected lines, circles and
boolean operations in between them. While possible to make polygons with
circular arcs using boolean operations of these it is not a desirable
solution. Preferred solution is of course to add lines and then needed
circular arcs.


Have code below that for some angles cases succeed making a polygon with
half circle and a line connecting the two endpoints example in attached
picture. It seems to work perfect for different angles then circle is to
the right the first if condition if(p2.y() < p3.y()) in code snippet
below. But for the second if condition if(p2.y() > p3.y()) it only seems
to work then pointing to the left the angle=PI but otherwise fail with
the error message at bottom. Suspect this is because something does not
fit perfectly together for example the points on the circle. Guess I am
not the first person try to do this. Anybody have any suggestions how to
make it work?


typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 K_Point_2;
typedef CGAL::Arr_circle_segment_traits_2<Kernel>::Point_2 Apoint_2;
typedef Kernel::Circle_2 K_Circle_2;
typedef CGAL::Gps_circle_segment_traits_2<Kernel> Traits_2; /* The
traits class Gps_circle_segment_traits_2 models the
GeneralPolygonSetTraits_2 concept.
                                                                      *
It enables Boolean set-operations on general polygons bounded by linear
segments or circular arcs. It should be parameterized with a kernel. */
typedef CGAL::General_polygon_set_2<Traits_2> Polygon_set_2;
typedef Traits_2::General_polygon_2 Polygon_2;
typedef Traits_2::General_polygon_with_holes_2 Polygon_with_holes_2;
typedef Traits_2::Curve_2                                 Curve_2;
typedef Traits_2::X_monotone_curve_2 X_monotone_curve_2;
typedef Traits_2::CoordNT                                 coordnt;

tool_type::tool_type(point_type pOld, point_type pNew)
{
   const double xOld = pOld.x;
   const double yOld = pOld.y;
   const double xNew = pNew.x;
   const double yNew = pNew.y;
   const double radius = 6;
   const double angle = atan2(yNew-yOld, xNew-xOld);
   const FT radiusFT = radius;

   {
     const K_Point_2 p0(xOld+radius*std::cos(angle + M_PI/2),
yOld+radius*std::sin(angle + M_PI/2)); // angle zero and pNew to the right
     const K_Point_2 p1(xOld+radius*std::cos(angle - M_PI/2),
yOld+radius*std::sin(angle - M_PI/2)); // of pOld arrangement below:
     const K_Point_2 p2(xNew+radius*std::cos(angle - M_PI/2),
yNew+radius*std::sin(angle - M_PI/2)); //   p0 p3
     const K_Point_2 p3(xNew+radius*std::cos(angle + M_PI/2),
yNew+radius*std::sin(angle + M_PI/2)); //   p1 p2

     {
       Polygon_2 pgn;
       const K_Circle_2 tool_circle(K_Point_2(xOld,yOld),
radiusFT*radiusFT);
       const K_Circle_2 tool_circle2(p2, p3, CGAL::COUNTERCLOCKWISE);
       toolFront = construct_polygon(tool_circle);
       monotone_curves_type cc;// = construct_circular_arc(tool_circle2,
radiusFT, p2, p3, CGAL::COUNTERCLOCKWISE); // Test function remove!!
then done
       if(p2.y() < p3.y())
       {
         const Apoint_2 p(p2.x(), p2.y());
         const K_Point_2 pRight(xNew + radius, yNew);
         const Apoint_2 r(p3.x(), p3.y());
         const K_Circle_2 c(p2, pRight, p3);
         const K_Point_2 center = c.center();
         const Apoint_2 q(pRight.x(), pRight.y());

         cc.x1 = X_monotone_curve_2(c, p, q, CGAL::COUNTERCLOCKWISE);
         cc.x2 = X_monotone_curve_2(c, q, r, CGAL::COUNTERCLOCKWISE);
         cc.valid = 2;
       }
       if(p2.y() > p3.y())
       {
         const Apoint_2 p(p2.x(), p2.y());
         const K_Point_2 pLeft(xNew - radius, yNew);
         const Apoint_2 r(p3.x(), p3.y());
         const K_Circle_2 c(p2, pLeft, p3);
         const K_Point_2 center = c.center();
         const Apoint_2 q(pLeft.x(), pLeft.y());

         cc.x1 = X_monotone_curve_2(c, p, q, CGAL::COUNTERCLOCKWISE);
         cc.x2 = X_monotone_curve_2(c, q, r, CGAL::COUNTERCLOCKWISE);
         cc.valid = 2;
       }
       pgn.push_back(cc.x1);
       pgn.push_back(cc.x2);
       pgn.push_back(X_monotone_curve_2(p3, p2));

       closed.insert(pgn);
     }
   }
}

terminate called after throwing an instance of
'CGAL::Precondition_exception'

   what(): CGAL ERROR: precondition violation!

Expr: cv1.point_position (p) == EQUAL && cv2.point_position (p) == EQUAL

File: /usr/include/CGAL/Arr_circle_segments_traits2.h

Line: 255

Aborted


For the curios persons it should be used to iteratively calculate tool
path for a CNC machine. If Successful I will try to add it to the CAM
module called path workbench in Freecad. At first tried to use the
builtin representation of material and tool shape but seems I got some
accuracy problem. Then I tried Open Cascade which Freecad use internally
or are built upon so to say but calculations where slow. So then I
decided to switch to CGAL as I had seen before it have an impressive
list of developers so guess it is the best possible to get.



Nicklas SB Karlsson


#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Gps_circle_segment_traits_2.h>
#include <CGAL/General_polygon_set_2.h>

#include <boost/iterator/function_output_iterator.hpp>

#include <QtGui/QPainterPath>
#include <CGAL/Qt/GraphicsViewNavigation.h>

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QtMath>
#include <QDebug>

typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2                                   K_Point_2;
typedef CGAL::Arr_circle_segment_traits_2<Kernel>::Point_2 Apoint_2;
typedef Kernel::Circle_2                                  K_Circle_2;
typedef CGAL::Gps_circle_segment_traits_2<Kernel>         Traits_2; /* The traits class Gps_circle_segment_traits_2 models the GeneralPolygonSetTraits_2 concept.
                                                                     * It enables Boolean set-operations on general polygons bounded by linear segments or circular arcs. It should be parameterized with a kernel. */
typedef CGAL::General_polygon_set_2<Traits_2>             Polygon_set_2;
typedef Traits_2::General_polygon_2                       Polygon_2;
typedef Traits_2::General_polygon_with_holes_2            Polygon_with_holes_2;
typedef Traits_2::Curve_2                                 Curve_2;
typedef Traits_2::X_monotone_curve_2                      X_monotone_curve_2;
typedef Kernel::FT                                        FT;
typedef Kernel::RT                                        RT;
typedef Traits_2::CoordNT                                 coordnt;

typedef struct
{
  X_monotone_curve_2 x1;
  X_monotone_curve_2 x2;
  int valid = 0;          // Number of valid monotone curves
} monotone_curves_type;

class tool_type
{
public :
  typedef struct
  {
    double x;
    double y;
  } point_type;

  Polygon_set_2 closed;		  // All four edges connected to a wire, used to face to subtract machined material from stock
  tool_type(point_type pOld, point_type pNew);
private :
};

int draw_General_Polygon_2(int argc, char **argv, Polygon_set_2 polygon);

int main(int argc, char **argv)
{
  Polygon_set_2 S;
  /* Boolean operations: do_instersect, intersection, join, difference, symmetric difference. */
  {
    tool_type::point_type oldPos = {.x=30.0, .y=0.0};
    tool_type::point_type newPos = {.x=25, .y=0};
    tool_type tool(oldPos, newPos);

    S.join(tool.closed);
  }

  return draw_General_Polygon_2(argc, argv, S);
}

tool_type::tool_type(point_type pOld, point_type pNew)
{
  const double xOld = pOld.x;
  const double yOld = pOld.y;
  const double xNew = pNew.x;
  const double yNew = pNew.y;
  const double radius = 6;
  const double angle = atan2(yNew-yOld, xNew-xOld);
  const FT radiusFT = radius;

  {
    const K_Point_2 p0(xOld+radius*std::cos(angle + M_PI/2), yOld+radius*std::sin(angle + M_PI/2)); // angle zero and pNew to the right
    const K_Point_2 p1(xOld+radius*std::cos(angle - M_PI/2), yOld+radius*std::sin(angle - M_PI/2)); // of pOld arrangement below:
    const K_Point_2 p2(xNew+radius*std::cos(angle - M_PI/2), yNew+radius*std::sin(angle - M_PI/2)); //   p0 p3
    const K_Point_2 p3(xNew+radius*std::cos(angle + M_PI/2), yNew+radius*std::sin(angle + M_PI/2)); //   p1 p2

    {
      Polygon_2 pgn;
      const K_Circle_2 tool_circle(K_Point_2(xOld,yOld), radiusFT*radiusFT);
      const K_Circle_2 tool_circle2(p2, p3, CGAL::COUNTERCLOCKWISE);
      monotone_curves_type cc;// = construct_circular_arc(tool_circle2, radiusFT, p2, p3, CGAL::COUNTERCLOCKWISE); // Test function remove!! then done
      if(p2.y() < p3.y())
      {
        const Apoint_2 p(p2.x(), p2.y());
        const K_Point_2 pRight(xNew + radius, yNew);
        const Apoint_2 r(p3.x(), p3.y());
        const K_Circle_2 c(p2, pRight, p3);
        const K_Point_2 center = c.center();
        const Apoint_2 q(pRight.x(), pRight.y());

        cc.x1 = X_monotone_curve_2(c, p, q, CGAL::COUNTERCLOCKWISE);
        cc.x2 = X_monotone_curve_2(c, q, r, CGAL::COUNTERCLOCKWISE);
        cc.valid = 2;
      }
      if(p2.y() > p3.y())
      {
        const Apoint_2 p(p2.x(), p2.y());
        const K_Point_2 pLeft(xNew - radius, yNew);
        const Apoint_2 r(p3.x(), p3.y());
        const K_Circle_2 c(p2, pLeft, p3);
        const K_Point_2 center = c.center();
        const Apoint_2 q(pLeft.x(), pLeft.y());

        cc.x1 = X_monotone_curve_2(c, p, q, CGAL::COUNTERCLOCKWISE);
        cc.x2 = X_monotone_curve_2(c, q, r, CGAL::COUNTERCLOCKWISE);
        cc.valid = 2;
      }
      pgn.push_back(cc.x1);
      pgn.push_back(cc.x2);
      pgn.push_back(X_monotone_curve_2(p3, p2));

      closed.insert(pgn);
    }
  }
}

static QPainterPath construct_path(const Polygon_2 &pgn)
{
  QPainterPath result;

  Q_ASSERT(pgn.orientation() == CGAL::CLOCKWISE ||
           pgn.orientation() == CGAL::COUNTERCLOCKWISE);

  // Degenerate polygon, ring.size() < 3
  if (pgn.orientation() == CGAL::ZERO)
    {
      qWarning() << "construct_path: Ignoring degenerated polygon";
      return  result;
    }

  const bool isClockwise = pgn.orientation() == CGAL::CLOCKWISE;

  Polygon_2::Curve_const_iterator current = pgn.curves_begin();
  Polygon_2::Curve_const_iterator end = pgn.curves_end();

  result.moveTo(CGAL::to_double(current->source().x()),
                CGAL::to_double(current->source().y()));

  do
    {
      const Polygon_2::X_monotone_curve_2 &curve = *current;
      const auto &source = curve.source();
      const auto &target = curve.target();

      if (curve.is_linear())
        {
          std::cout << "curve.linear() = (" << CGAL::to_double(source.x()) << ", " << CGAL::to_double(source.y()) << ")<->(";
          std::cout << CGAL::to_double(target.x()) << ", " << CGAL::to_double(target.y()) << ")\n";
          result.lineTo(QPointF(CGAL::to_double(target.x()),
                                CGAL::to_double(target.y())));
        }
      else if (curve.is_circular())
        {
          const auto bbox = curve.supporting_circle().bbox();
          const QRectF rect(QPointF(bbox.xmin(), bbox.ymin()),
                            QPointF(bbox.xmax(), bbox.ymax()));
          const auto center = curve.supporting_circle().center();
          const double asource = qAtan2(CGAL::to_double(source.y() - center.y()),
                                        CGAL::to_double(source.x() - center.x()));
          const double atarget = qAtan2(CGAL::to_double(target.y() - center.y()),
                                        CGAL::to_double(target.x() - center.x()));
          double aspan = atarget - asource;
          if (aspan < -CGAL_PI || (qFuzzyCompare(aspan, -CGAL_PI) && !isClockwise))
            aspan += 2.0*CGAL_PI;
          else if (aspan > CGAL_PI || (qFuzzyCompare(aspan, CGAL_PI) && isClockwise))
            aspan -= 2.0*CGAL_PI;
          result.arcTo(rect, qRadiansToDegrees(-asource), qRadiansToDegrees(-aspan));
          std::cout << "curve.is_circular() center=" << center << " (" <<
                    CGAL::to_double(source.x()) << ", " << CGAL::to_double(source.y()) << ")<->(" <<
                    CGAL::to_double(target.x()) << ", " << CGAL::to_double(target.y()) << ")\n";
        }
      else   // ?!?
        {
          Q_UNREACHABLE();
        }
    }
  while (++current != end);

  return result;
}

int draw_General_Polygon_2(int argc, char **argv, Polygon_set_2 S)
{
  QApplication app(argc, argv);
  QGraphicsScene scene;

  // Insert the resulting polygons into the graphics scene
  S.polygons_with_holes(boost::make_function_output_iterator([&scene](const Polygon_with_holes_2 &pgn)
  {
    if (!pgn.is_unbounded())
      scene.addPath(construct_path(pgn.outer_boundary()), QPen(Qt::green, 0.0), Qt::darkGreen);

    Polygon_with_holes_2::Hole_const_iterator current = pgn.holes_begin();
    Polygon_with_holes_2::Hole_const_iterator end = pgn.holes_end();
    while (current != end)
      {
        scene.addPath(construct_path(*current), QPen(Qt::red, 0.0), Qt::darkRed);
        current++;
      }
  }));

  // And show the result
  QGraphicsView view;
  view.setBackgroundBrush(QColor("#073642"));
  view.setInteractive(true);
  view.setDragMode(QGraphicsView::ScrollHandDrag);
  scene.setSceneRect(scene.itemsBoundingRect());
  view.setScene(&scene);
  view.fitInView(scene.sceneRect(), Qt::KeepAspectRatio);
  view.scale(1, -1); // Revert Y-axis

  CGAL::Qt::GraphicsViewNavigation navigation;
  view.installEventFilter(&navigation);
  view.viewport()->installEventFilter(&navigation);
  view.setRenderHint(QPainter::Antialiasing);

  view.show();
  return app.exec();
}
file(GLOB ConstantToolAngle_SRC
"*.cxx"
"*.cpp"
"Samples.qrc")

target_sources(ConstantToolEngagementAngle PUBLIC ${ConstantToolAngle_SRC})
# Created by the script cgal_create_cmake_script
# This is the CMake script for compiling a CGAL application.

cmake_minimum_required(VERSION 3.1...3.15)
project(ConstantToolEngagementAngle CXX)


find_package(CGAL REQUIRED OPTIONAL_COMPONENTS Qt5)

if(CGAL_Qt5_FOUND)
  add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS)
endif()

add_executable(ConstantToolEngagementAngle)
add_subdirectory(src)

# create a target per cppfile
#file(
#  GLOB cppfiles
#  RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
#  ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
#foreach(cppfile ${cppfiles})
#  create_single_source_cgal_program("${cppfile}")
#endforeach()

if(CGAL_Qt5_FOUND)
  #target_link_libraries(draw_polygon PUBLIC CGAL::CGAL_Qt5)
  target_link_libraries(ConstantToolEngagementAngle PUBLIC CGAL::CGAL_Qt5)
endif()

Attachment: ConstantToolEngagementAngle.cbp
Description: application/codeblocks

Attachment: ConstantToolAngleCGAL.zip
Description: Zip archive




Archive powered by MHonArc 2.6.19+.

Top of Page