Adding multiple shapes using the FLK library - c++

I have been trying to make a checkered image.
I can print out everything just fine but I want to find a way to duplicate the shapes of different colors so that I won't have to wast time creating 64 rectangles. I really don't know where to go from here.
#include "Window.h"
#include "Graph.h"
#include "std_lib_facilities_5.h"
#include "Simple_window.h"
#include "FL/Fl_JPEG_Image.H"
int main()
try {
Here is the window being create using the Simple_window struct.
Point tl{ 100,100 };
Simple_window win{ tl,440,440,"Canvas" };
Find the maximum distances than can be given on a window and set the values up as integers (both going in x and y dimensions). x_grid and y_grid are dimensions of a single grid square.
int x_size = win.x_max();
int y_size = win.y_max();
int x_grid = 55;
int y_grid = 55;
Use a Lines class to build the grid. For loops are made to determine where the lines will be placed to form a grid.
Lines grid;
for (int x = x_grid; x < x_size; x += x_grid) {
grid.add(Point{ x,0 }, Point{ x,y_size });
}
for (int y = y_grid; y < y_size; y += y_grid) {
grid.add(Point{ 0,y }, Point{ x_size,y });
}
win.attach(grid);
So here I created two different colors but of the same size using the rectangle class.
So right now I have placed the squared at only one point. However like I said before, I need them to be all over the image. Is there any other way besides making 64 shapes where I can have them copies of the squares? I assume there are some loops involved.
Rectangle rx1(Point(55, 0), 55, 55);
Color moss_green(fl_rgb_color(173, 223, 173));
rx1.set_color(Color::invisible);
rx1.set_fill_color(moss_green);
win.attach(rx1);
Rectangle ry1(Point(0, 0), 55, 55);
Color cherry_blossom_pink(fl_rgb_color(255, 183, 197));
ry1.set_color(Color::invisible);
ry1.set_fill_color(cherry_blossom_pink);
win.attach(ry1);
win.wait_for_button();
}
catch (exception& e) {
cerr << "exception: " << e.what() << endl;
keep_window_open();
}
catch (...) {
cerr << "exception\n";
keep_window_open();
}

Related

How to remove green pixels from character green screen

I am a beginner with C++, so please forgive me, but I am trying to bring two images together. One of them is a character in a green screen and a real life location. I was able to successfully mix the two images together on Visual Studio, however, I'm trying to remove the green pixels from the character and replace them with the background image. How can I use the green pixels. Any form of help would be much appreciated. Here is my code:
#include <iostream>
#include <SFML/Graphics.hpp>
using namespace sf;
using namespace std;
int main()
{
Texture tex;
if (!tex.loadFromFile("yoda.png")) {
cout << "Couldn’t Load Yoda Image";
exit(1);
}
Texture tex2;
if (!tex2.loadFromFile("prague.png")) {
cout << "Couldn’t Load Prague Image";
exit(1);
}
Image yodaImage;
yodaImage = tex.copyToImage();
Image pragueImage;
pragueImage = tex2.copyToImage();
RenderWindow window(VideoMode(1024, 800), "Assignment 3");
Sprite sprite;
sprite.setTexture(tex);
Vector2u textureSize = tex.getSize();
sprite.setPosition((1024 - textureSize.x) / 2,
(800 - textureSize.y) / 2);
Vector2u sz = yodaImage.getSize();
for (int y = 0; y < sz.y; y++) {
for (int x = 0; x < sz.x; x++) {
Color pragueC = pragueImage.getPixel(x,y);
Color yodaC = yodaImage.getPixel(x,y);
Color mixedC(
pragueC.r / 2 + yodaC.r / 2,
pragueC.g / 2 + yodaC.g / 2,
pragueC.b / 2 + yodaC.b / 2 );
yodaImage.setPixel(0, 0, mixedC);
}
}
tex.loadFromImage(yodaImage);
window.clear();
window.draw(sprite);
window.display();
while (true);
}

turtle graphics: starting a new line

Sorry for the massive block of code ;w;
I'm learning C++, and this is an assignment I'm stuck on- I'm supposed to be making a brick wall with alternating rows offset by 1/2 bricks, and I'm supposed to be using a nested loop to do so.
I've got the functions to draw the full brick and half bricks, and I've successfully been able to create a full line of 9 bricks(9 being how many bricks can span the window) and I'm stuck on the next step. I need to make the program draw the next line after the first one is finished, but "\n" and "cout << endl;" only affect the main window and not the "TurtleWindow" that OpenCV opens. All I have in that regard is that it has something to do with the "changePosition" command, but I'm not sure how to add that in to my loop. If I set position to some specific (x, y) coords, then wouldn't it just keep setting the "bricks" in that position every loop?
Any help would be appreciated, I feel like I'm so close to the solution but this is stumping me...
// BrickWall.cpp : This file contains the 'main' function. Program execution begins
//and ends there.
//
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <stdio.h>
#include <math.h>
using namespace cv;
using namespace std;
#define M_PI 3.14159265358979323846264338327950288
#define degToRad(angleInDegrees) ((angleInDegrees) * M_PI / 180.0)
char wndname[] = "TurtleWindow";
Mat image = Mat::zeros(500, 500, CV_8UC3);
Scalar WHITE(255, 255, 255);
const int DELAY = 1;
Point _curPosition(250, 250);
int _direction = 0;
void init()
{
imshow(wndname, image);
waitKey(DELAY);
}
//
// Move the pen to the given coordinates without leaving a mark
//
// Note (0,0) refers to the upper left corner
// (500,500) refers to the bottom right corner
//
void changePosition(int x, int y)
{
_curPosition.x = x;
_curPosition.y = y;
}
//
// point in the direction given in degrees
// 0 ==> point right
// 90 ==> point down
// 180 ==> point left
// 270 ==> point up
//
void changeDirection(int direction)
{
_direction = direction;
}
//
// Moves the pen forward the given number of pixels
// Note leaves a mark creating a line from the previous point
// to the new point
//
void moveForward(int nPixels)
{
int x = static_cast<int>(round(nPixels * cos(degToRad(_direction))));
int y = static_cast<int>(round(nPixels * sin(degToRad(_direction))));
Point newPoint = Point(x + _curPosition.x, y + _curPosition.y);
line(image, _curPosition, newPoint, WHITE);
_curPosition = newPoint;
// cout << "moved to " << newPoint.x << "," << newPoint.y << endl;
imshow(wndname, image);
waitKey(DELAY);
}
void fullBrick()
// changePosition(25, 25);
{
changeDirection(0);
moveForward(50);
changeDirection(90);
moveForward(20);
changeDirection(180);
moveForward(50);
changeDirection(270);
moveForward(20);
changeDirection(0);
moveForward(50);
}
void halfBrick()
//changePosition(25, 45);
{
changeDirection(0);
moveForward(25);
changeDirection(90);
moveForward(20);
changeDirection(180);
moveForward(25);
changeDirection(270);
moveForward(20);
}
int main()
{
int counter;
int counterWall;
counterWall = 0;
counter = 0;
init();
changePosition(25, 25);
while (counter < 20)
{
do
{
changeDirection(0);
moveForward(50);
changeDirection(90);
moveForward(20);
changeDirection(180);
moveForward(50);
changeDirection(270);
moveForward(20);
changeDirection(0);
moveForward(50);
counterWall++;
} while (counterWall < 9);
counter++;
}
waitKey();
}
edit: thanks everyone for the advice! I was fully intending to use a nested loop in the end(and did use one, so no lost points there!) and was able to realize there was nothing stopping me from looping the bricks like a snake. I had to turn the assignment in before I could try any of the changes you guys offered, but I'll be sure to keep them in mind for future assignments!
and here's a link to the picture of the final product, I've never been happier to see a brick wall in my life
Brick Wall Picture

How to determine if a color is on range

I'm trying to filter images by the dominant color its appears in it. Thats is done, now I want to know if the obtained color is in range from a defined range of colors. In this particular case I want to know if the is inside orange range color.
I saw function 'inrange' but i don't think this case help me. By this I did next code:
Scalar ORANGE_MIN = Scalar(18, 40, 90);
Scalar ORANGE_MAX = Scalar(27, 255, 255);
bool in_range(Scalar color, Scalar orange_min, Scalar orange_max)
{
bool result = false;
if ((color.val[0] > orange_min.val[0] && color.val[0] < orange_max.val[0]) &&
(color.val[1] > orange_min.val[1] && color.val[1] < orange_max.val[1]) &&
(color.val[2] > orange_min.val[2] && color.val[2] < orange_max.val[2]))
{
result = true;
}
return result;
}
Something its wrong because not filter like I expected.
Can anyone help me?
Thanks!
I'll follow a slightly different approach. Instead of defining the range intervals for all predefined colors, you can:
Define your predefined colors. This would be the palette of your possible colors
Given the color you want to check, compute the distance from all colors in your palette, and keep the nearest palette color.
Check if the found palette color is near enough.
In this small sample I used BGR color space, since the euclidean distance (norm of the two colors) is well behaved.
You can use another color space, like HSV, but you need to find a suitable distance. You can't use just the H value, since you'll miss black / white / gray colors (as mentioned by #MSalters).
So, given for example your color almost orange 20, 130, 250, with an appropriate palette you'll get something like:
[20, 130, 250] is similar to orange
Distance with nearest color [0, 127, 255] is 20.8327
Code:
#include <opencv2/opencv.hpp>
#include <vector>
#include <map>
#include <string>
using namespace cv;
using namespace std;
// Needed to put Vec3b into a std::map
struct lessVec3b
{
bool operator()(const Vec3b& lhs, const Vec3b& rhs) {
return (lhs[0] != rhs[0]) ? (lhs[0] < rhs[0]) : ((lhs[1] != rhs[1]) ? (lhs[1] < rhs[1]) : (lhs[2] < rhs[2]));
}
};
int main()
{
// Define a set of predefined BGR colors
map<Vec3b, string, lessVec3b> palette;
palette[Vec3b(0, 0, 0)] = "black";
palette[Vec3b(0, 0, 255)] = "red";
palette[Vec3b(0, 255, 0)] = "green";
palette[Vec3b(255, 0, 0)] = "blue";
palette[Vec3b(0, 127, 255)] = "orange";
// Your color
Vec3b my_color(20, 130, 250); // almost orange
// Look for nearest color in palette
Vec3b nearest_color;
string color_name;
float min_distance = FLT_MAX;
for (const auto& pal : palette)
{
float dist = norm(pal.first, my_color);
if (dist < min_distance)
{
nearest_color = pal.first;
color_name = pal.second;
min_distance = dist;
}
}
// Define a distance. This will behave like your ranges
float th_distance = 1000.f;
if (min_distance < th_distance)
{
cout << my_color << " is similar to " << color_name << endl;
}
else
{
cout << my_color << " is not in the palette" << endl;
}
cout << "Distance with nearest color " << nearest_color << " is " << min_distance << endl;
return 0;
}
Convert ORANGE_MIN, ORANGE_MAX, and color to HSL (HSV) color models and check that the hue is within the required range. See, e.g., http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/ for the math.
UPDATE
Saturation and lightness should be checked against some ranges as well, see the comments below. Thanks MSalters for pointing this out.

How to calculate distance from point o filled/unfilled rectangle

I am visualising different sorts of geometries using Qt 5.
There I have a QRect that is either visualised as filled or not.
Now I want to calculate the distance of a QPoint to that rectangle using boost::geometry.
A point within the rectangle should have a distance of 0 when filled, and the distance to the next line when not filled.
Since the documentation of Box does not mention that it is a shape I thought I could use it for this case and adapted the Box concept to QRect.
The following example does not work though, since a Box is treated as shape and therefore always "filled".
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <QtCore/QPoint>
#include <QtCore/QRect>
BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET(QPoint, int, boost::geometry::cs::cartesian, x, y, setX, setY);
namespace boost { namespace geometry {
namespace traits
{
template <> struct tag<QRect> { typedef box_tag type; };
template <> struct point_type<QRect> { typedef QPoint type; };
template <std::size_t Index, std::size_t Dimension>
struct indexed_access<QRect, Index, Dimension>
{
typedef typename geometry::coordinate_type<QRect>::type coordinate_type;
static inline coordinate_type get(const QRect &r)
{
if (Index == boost::geometry::min_corner)
return geometry::get<Dimension>(r.topLeft());
else
return geometry::get<Dimension>(r.bottomRight());
}
};
}
}}
double distance(const QPoint &p, const QRect &r, const bool filled)
{
if (filled && r.contains(p))
return 0.0;
else
return boost::geometry::distance(p, r);
}
int main()
{
QRect r(QPoint(0, 0), QPoint(20, 10));
QPoint p(5, 5); // whithin rect
// 0, instead of 5
std::cout << "not filled: " << distance(p, r, false) << '\n';
// 0, as expected
std::cout << "filled: " << distance(p, r, true) << '\n';
}
Run g++ -Wall -O2 -fPIC main.cpp -I/usr/include/qt -lQtCore to build this on Linux.
I could of course use the LineString for the not filled case, though then there would be dynamic allocations.
Unless I create a manualy adaption which uses an underlying QRect, which would be quite some work.
How do I best tackle this issue?
Indeed you're right line-string is required because Box implies a filled shape. Same thing for polygons, actually, in my quick test.
You could of course create a fake "holey" polygon that has an edge of some small width. But that's cheating and certainly less efficient
Indeed, you can use linestring here:
Live On Coliru
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/linestring.hpp>
using namespace boost::geometry;
int main()
{
using Point = model::d2::point_xy<double>;
using Rect = model::linestring<Point>;
Rect rect;
rect.insert(rect.end(), {
Point { 0, 0 },
Point { 10, 0 },
Point { 10, 20 },
Point { 0, 20 },
Point { 0, 0 },
});
std::cout << "distance point within: " << distance(rect, Point(5, 5)) << '\n'; // 0
std::cout << "distance point not within: " << distance(rect, Point(15, 5)) << '\n'; // 5
}
Which prints
distance point within: 5
distance point not within: 5
I don't see any reason to believe that the linestring is less efficient than the polygon (it's basically the same as just the outer ring of a polygon).
However, indeed box testing might be faster. I suggest you profile it. If it's faster, just use the box in case the shape is known to be "filled" and a linestring otherwise.
A relative easy way to support non-filled QRect is to use the LineString concept.
To avoid overhead of a allocations std::array could be used.
Based on the intial code, the following parts need to be added:
#include <array>
using RectLineString = std::array<QPoint, 5>;
BOOST_GEOMETRY_REGISTER_LINESTRING(RectLineString)
double distance(const QPoint &p, const QRect &r, const bool filled)
{
if (filled && r.contains(p))
return 0.0;
else
{
RectLineString rls;
fillRectLineString(rls, rect);
return boost::geometry::distance(p, rls);
}
}
What fillrectLineString should look like depends on how you want to handle the issue that QRect::bottomRight() returns QPoint(rect.x() + rect.width() - 1, rect.y() + rect.height() - 1).
So I provide two versions here:
// bottomRight() is QPoint(rect.x() + rect.width() - 1, rect.y() + rect.height() - 1)
void fillRectLineString1(RectLineString &rls, const QRect &rect)
{
rls[0] = rect.topLeft();
rls[1] = rect.topRight();
rls[2] = rect.bottomRight();
rls[3] = rect.bottomLeft();
rls[4] = rect.topLeft();
}
// bottomRight() is QPoint(rect.x() + rect.width(), rect.y() + rect.height())
void fillRectLineString2(RectLineString &rls, const QRect &rect)
{
rls[0] = QPoint(rect.x(), rect.y());
rls[1] = QPoint(rect.x() + rect.width(), rect.y());
rls[2] = QPoint(rect.x() + rect.width(), rect.y() + rect.height());
rls[3] = QPoint(rect.x(), rect.y() + rect.height());
rls[4] = QPoint(rect.x(), rect.y());
}

Writing text to a postscript file using several class objects

(Full question is listed at the bottom)
I have an assignment that requires me to write text to a postscript file that allows me to draw "Gosper" curves using recursion. However, the test driver (GosperDriver.cpp) my professor has given us resembles the following:
#include "Gosper.h"
#include <iostream>
using namespace std;
int main( )
{
// test right hexagonal Gosper curve at level 4
Gosper gosper1( 100, 100, 0 );
gosper1.rightCurve( 4, 4 );
// test left hexagonal Gosper curver at level 4
Gosper gosper2( 500, 100, 0 );
gosper2.leftCurve( 4, 4 );
// test right hexagonal Gosper curve at level 3
Gosper gosper3( 100, 400, 0 );
gosper3.rightCurve( 3, 6 );
// test left hexagonal Gosper curver at level 3
Gosper gosper4( 500, 400, 0 );
gosper4.leftCurve( 3, 6 );
// test right hexagonal Gosper curve at level 2
Gosper gosper5( 100, 600, 0 );
gosper5.rightCurve( 2, 8 );
// test left hexagonal Gosper curver at level 2
Gosper gosper6( 500, 600, 0 );
gosper6.leftCurve( 2, 8 );
// test right hexagonal Gosper curve at level 1
Gosper gosper7( 100, 700, 0 );
gosper7.rightCurve( 1, 10 );
// test left hexagonal Gosper curver at level 1
Gosper gosper8( 500, 700, 0 );
gosper8.leftCurve( 1, 10 );
}
Gosper.h includes Turtle.h, which contains the "draw" functions which are vital to the project.
Here are my Gosper.h, Gosper.cpp, Turtle.h, and Turtle.cpp files, in that order (I'll cut out the unnecessary code, which controls drawing):
Gosper.h:
// Sierpinski Class
#ifndef GOSPER_H
#define GOSPER_H
#include "Turtle.h"
#include <iostream>
#include <fstream>
using namespace std;
class Gosper : Turtle
{
public:
Gosper(float initX=0.0, float initY=0.0, float initA=0.0);
void leftCurve( int l, float d ); // Draw level l left curve with dist d
void rightCurve( int l, float d ); // Draw level l right curve with dist d
};
#endif
Gosper.cpp:
#include <iostream>
#include <string>
#include "Gosper.h"
// Initialization and such.
Gosper::Gosper(float initX, float initY, float initA)
{
}
void Gosper::leftCurve(int level, float d)
{
// Code that uses draw() function of Turtle.h and Turtle.cpp
}
void Gosper::rightCurve(int level, float d)
{
// Same as above
}
Turtle.h:
#ifndef TURTLE_H
#define TURTLE_H
#include <iostream>
#include <fstream>
#include <math.h>
using namespace std;
const float PI = 3.1459265;
class Turtle {
public:
Turtle(float initX = 0.0, float initY = 0.0, float initA = 0.0);
~Turtle();
void draw( float d ); // draw line by distance d
void move( float d ); // simply move by distance d
void turn( float a ); // turn by angle a
private:
ofstream out;
float angle; // current angle
};
Turtle.cpp:
#include "Turtle.h"
#include <iostream>
#include <fstream>
Turtle::Turtle(float initX, float initY, float initA)
{
out.open("output.ps");
out << "%!PS-Adobe-2.0" << endl;
out << initX << "\t" << initY << "\tmoveto" << endl;
angle = initA;
}
Turtle::~Turtle()
{
out << "stroke" << endl;
out << "showpage" << endl;
}
void Turtle::turn(float a)
{
angle += a;
}
void Turtle::draw(float d)
{
float dX, dY;
dX = d * cos(PI * angle / 180);
dY = d * sin(PI * angle / 180);
out << dX << "\t" << dY << "\trlineto" << endl;
}
void Turtle::move(float d)
{
float dX, dY;
dX = d * cos(PI * angle / 180);
dY = d * sin(PI * angle / 180);
out << dX << "\t" << dY << "\trmoveto" << endl;
}
#endif
Okay, so now that you've seen my code, here's my problem:
I want to write the text for every Gosper class object in GosperDriver.cpp into one postscript file. As it is right now, any attempt to do that will result in the previous block of text in the designated output.ps to be overwritten. At the moment, I can only write the text necessary for ONE Gosper class object. I have had to comment out every Gosper object declaration in Gosperdriver.cpp but one, in order to test if my program is working correctly.
In short, I need to write the text necessary to output.ps for every Gosper object in GosperDriver.cpp, but it isn't working because it will only let me write for one at a time. What do I do?
Bonus question about inheritance: right now, my "starting point" for each Gosper drawing keeps being set at x = 0 and y = 0. As seen by the Gosper object declarations, none of the parameters contain 0 for x or y. Something's gone wonky. What's happening?
Thanks in advance to anyone who can answer one or both of these questions! :)
You can use
out.open("output.ps", std::fstream::in | std::fstream::out | std::fstream::app);
to open the file in append mode. Meaning old content will not be overwritten.
You will however need to add something to detect if the header
out << "%!PS-Adobe-2.0" << endl; has already been written. (I assume you need that exactly once per file.)
To avoid opening and closing the file all the time you could also create a separate class that will open the file, initialize it (write the header) and then use this class to write all your contents and close the file afterwards.
For bonus points use RAII to make the class automatically take care of the file.