1 /**********************************************************************
2  *
3  * GEOS - Geometry Engine Open Source
4  * http://geos.osgeo.org
5  *
6  * Copyright (C) 2001-2002 Vivid Solutions Inc.
7  *
8  * This is free software; you can redistribute and/or modify it under
9  * the terms of the GNU Lesser General Public Licence as published
10  * by the Free Software Foundation.
11  * See the COPYING file for more information.
12  *
13  **********************************************************************/
14 
15 #include <cmath>
16 
17 #include <geos/geom/GeometryFactory.h>
18 #include <geos/geom/CoordinateArraySequence.h>
19 #include <geos/geom/Coordinate.h>
20 #include "bigtest.h"
21 
22 #define PI 3.14159265358979
23 
24 using namespace geos::geom;
25 
26 Polygon*
createBox(GeometryFactory * fact,double minx,double miny,int nSide,double segLen)27 GeometryTestFactory::createBox(GeometryFactory* fact, double minx, double miny, int nSide, double segLen)
28 {
29     CoordinateSequence* pts = createBox(minx, miny, nSide, segLen);
30     return fact->createPolygon(fact->createLinearRing(pts), nullptr);
31 }
32 
33 CoordinateSequence*
createBox(double minx,double miny,int nSide,double segLen)34 GeometryTestFactory::createBox(double minx, double miny, int nSide, double segLen)
35 {
36     int i;
37     CoordinateArraySequence* pts = new CoordinateArraySequence();
38     double maxx = minx + nSide * segLen;
39     double maxy = miny + nSide * segLen;
40 
41     for(i = 0; i < nSide; i++) {
42         double x = minx + i * segLen;
43         double y = miny;
44         pts->add(Coordinate(x, y));
45     }
46     for(i = 0; i < nSide; i++) {
47         double x = maxx;
48         double y = miny + i * segLen;
49         pts->add(Coordinate(x, y));
50     }
51     for(i = 0; i < nSide; i++) {
52         double x = maxx - i * segLen;
53         double y = maxy;
54         pts->add(Coordinate(x, y));
55     }
56     for(i = 0; i < nSide; i++) {
57         double x = minx;
58         double y = maxy - i * segLen;
59         pts->add(Coordinate(x, y));
60     }
61     pts->add(pts->getAt(0));
62     return pts;
63 }
64 
65 /**
66  * Creates a circle
67  * @param x the centre x coord
68  * @param y the centre y coord
69  * @param size the size of the envelope of the star
70  * @param nPts the number of points in the star
71  */
72 CoordinateSequence*
createCircle(double basex,double basey,double size,uint32_t nPts)73 GeometryTestFactory::createCircle(double basex, double basey, double size, uint32_t nPts)
74 {
75     CoordinateArraySequence* pts = new CoordinateArraySequence(nPts + 1);
76     double len = size / 2.0;
77 
78     for(int i = 0; i < nPts; i++) {
79         double ang = i * (2 * PI / nPts);
80         double x = len * cos(ang) + basex;
81         double y = len * sin(ang) + basey;
82         pts->add(Coordinate(x, y));
83     }
84     pts->add(Coordinate(pts->getAt(0)));
85     return pts;
86 }
87 
88 Polygon*
createCircle(GeometryFactory * fact,double basex,double basey,double size,uint32_t nPts)89 GeometryTestFactory::createCircle(GeometryFactory* fact, double basex, double basey, double size, uint32_t nPts)
90 {
91     CoordinateSequence* pts = createCircle(basex, basey, size, nPts);
92     return fact->createPolygon(fact->createLinearRing(pts), nullptr);
93 }
94 
95 /**
96  * Creates a star from a "circular" sine wave
97  * @param basex the centre x coord
98  * @param basey the centre y coord
99  * @param size the size of the envelope of the star
100  * @param armLen the length of an arm of the star
101  * @param nArms the number of arms of the star
102  * @param nPts the number of points in the star
103  */
104 CoordinateSequence*
createSineStar(double basex,double basey,double size,double armLen,int nArms,int nPts)105 GeometryTestFactory::createSineStar(double basex, double basey, double size, double armLen, int nArms, int nPts)
106 {
107     double armBaseLen = size / 2 - armLen;
108     if(armBaseLen < 0) {
109         armBaseLen = 0.5;
110     }
111 
112     double angInc = 2 * PI / nArms;
113     int nArmPt = nPts / nArms;
114     if(nArmPt < 5) {
115         nArmPt = 5;
116     }
117 
118     //int nPts2=nArmPt*nArms;
119     CoordinateArraySequence* pts = new CoordinateArraySequence();
120 
121     double starAng = 0.0;
122 
123     for(int iArm = 0; iArm < nArms; iArm++) {
124         for(int iArmPt = 0; iArmPt < nArmPt; iArmPt++) {
125             double ang = iArmPt * (2 * PI / nArmPt);
126             double len = armLen * (1 - cos(ang) / 2) + armBaseLen;
127             double x = len * cos(starAng + iArmPt * angInc / nArmPt) + basex;
128             double y = len * sin(starAng + iArmPt * angInc / nArmPt) + basey;
129 
130             // FIXME - mloskot: Number of problems here:
131             // - add() method makes a copy
132             pts->add(Coordinate(x, y));
133         }
134         starAng += angInc;
135     }
136     // FIXME - mloskot: The same problems as above
137     pts->add(pts->getAt(0));
138     return pts;
139 }
140 
141 Polygon*
createSineStar(GeometryFactory * fact,double basex,double basey,double size,double armLen,int nArms,int nPts)142 GeometryTestFactory::createSineStar(GeometryFactory* fact, double basex, double basey, double size, double armLen,
143                                     int nArms, int nPts)
144 {
145     CoordinateSequence* pts = createSineStar(basex, basey, size, armLen, nArms, nPts);
146     return fact->createPolygon(fact->createLinearRing(pts), nullptr);
147 }
148