📄 cvgstrokegroup.cpp
字号:
/* GHelm - Nautical Navigation Software * Copyright (C) 2004 Jon Michaelchuck * * This application is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */#include "cvgstrokegroup.h"#include "cvgutil.h"#include "cvg.h"#include <iostream>#include <GL/gl.h>#include <GL/glu.h>CVGStrokeGroup::CVGStrokeGroup() : width(1), loop(false), linecap(LINECAP_BUTT), linejoint(LINEJOINT_MITER){ rgb[0] = rgb[1] = rgb[2] = 0;}CVGStrokeGroup::~CVGStrokeGroup(){ // NOTE we don't delete the verts pointers; these are taken // care of in the shape classes.}/** * Load stroke group * @param doc xml doc * @param cur xml cursor * @return 0 on success, -1 on failure */int CVGStrokeGroup::Load(xmlDocPtr doc, xmlNodePtr cur){ xmlChar *prop; prop = xmlGetProp(cur, (const xmlChar *)"stroke"); if (prop) { std::string stroke = (const char *)prop; if (stroke.size() != 7) { std::cout << "CVGStrokeGroup::Load: bad parameter" << std::endl; return -1; } rgb[0] = _hex_to_dec(stroke.substr(1,2))/255.0; rgb[1] = _hex_to_dec(stroke.substr(3,2))/255.0; rgb[2] = _hex_to_dec(stroke.substr(5,2))/255.0; } prop = xmlGetProp(cur, (const xmlChar *)"stroke-width"); if (prop) width = atof((const char *)prop); prop = xmlGetProp(cur, (const xmlChar *)"stroke-linecap"); if (prop) { if (!xmlStrcmp(prop, (const xmlChar *) "butt")) linecap = LINECAP_BUTT; else if (!xmlStrcmp(prop, (const xmlChar *) "round")) linecap = LINECAP_ROUND; else if (!xmlStrcmp(prop, (const xmlChar *) "square")) linecap = LINECAP_SQUARE; else std::cerr << "CVGStrokeGroup::Load: Unknown linecap " << prop << std::endl; } prop = xmlGetProp(cur, (const xmlChar *)"stroke-linejoint"); if (prop) { if (!xmlStrcmp(prop, (const xmlChar *) "miter")) linejoint = LINEJOINT_MITER; else if (!xmlStrcmp(prop, (const xmlChar *) "round")) linejoint = LINEJOINT_ROUND; else if (!xmlStrcmp(prop, (const xmlChar *) "bevel")) linejoint = LINEJOINT_BEVEL; else std::cerr << "CVGStrokeGroup::Load: Unknown linejoint " << prop << std::endl; } return 0;}/** Draw stroke group */void CVGStrokeGroup::Render(){ glColor3fv(rgb); double dx, dy; double butt_dx, butt_dy; double theta; double lastv0[2]; double lastv1[2]; double firstv0[2]; double firstv1[2]; double vert0[2]; double vert1[2]; std::vector<double *>::iterator it; for (it = verts.begin(); (it+1) != verts.end(); ++it) { vert0[0] = (*it)[0]; vert0[1] = (*it)[1]; vert1[0] = (*(it+1))[0]; vert1[1] = (*(it+1))[1]; dx = vert1[0] - vert0[0]; dy = vert1[1] - vert0[1]; if (dx == 0) { butt_dx = width/2; butt_dy = 0; } else { theta = atan(dy/dx); butt_dx = sin(theta) * width/2; butt_dy = cos(theta) * width/2; } glBegin(GL_QUADS); glVertex2d(vert0[0] - butt_dx, vert0[1] + butt_dy); glVertex2d(vert0[0] + butt_dx, vert0[1] - butt_dy); glVertex2d(vert1[0] + butt_dx, vert1[1] - butt_dy); glVertex2d(vert1[0] - butt_dx, vert1[1] + butt_dy); glEnd(); if (it != verts.begin()) { switch (linejoint) { case LINEJOINT_MITER: break; case LINEJOINT_ROUND: { float radius = width/2; glPushMatrix(); glTranslatef(vert0[0], vert0[1], 0); glBegin(GL_POLYGON); for (int i=0; i <= 360; i += 10) { float radians = -i * DEG2RAD; glVertex2f(cos(radians) * radius, sin(radians) * radius); } glEnd(); glPopMatrix(); } break; case LINEJOINT_BEVEL: glBegin(GL_QUADS); glVertex2dv(lastv0); glVertex2d(vert0[0] + butt_dx, vert0[1] - butt_dy); glVertex2dv(lastv1); glVertex2d(vert0[0] - butt_dx, vert0[1] + butt_dy); glEnd(); break; default: break; } } else { firstv0[0] = vert0[0] - butt_dx; firstv0[1] = vert0[1] + butt_dy; firstv1[0] = vert0[0] + butt_dx; firstv1[1] = vert0[1] - butt_dy; } lastv0[0] = vert1[0] + butt_dx; lastv0[1] = vert1[1] - butt_dy; lastv1[0] = vert1[0] - butt_dx; lastv1[1] = vert1[1] + butt_dy; } vert0[0] = (*it)[0]; vert0[1] = (*it)[1]; vert1[0] = (*(verts.begin()))[0]; vert1[1] = (*(verts.begin()))[1]; if (loop) { dx = vert0[0] - vert1[0]; dy = vert0[1] - vert1[1]; if (dx == 0) { butt_dx = width/2; butt_dy = 0; } else { theta = atan(dy/dx); butt_dx = sin(theta) * width/2; butt_dy = cos(theta) * width/2; } glBegin(GL_QUADS); glVertex2d(vert0[0] - butt_dx, vert0[1] + butt_dy); glVertex2d(vert0[0] + butt_dx, vert0[1] - butt_dy); glVertex2d(vert1[0] + butt_dx, vert1[1] - butt_dy); glVertex2d(vert1[0] - butt_dx, vert1[1] + butt_dy); glEnd(); switch (linejoint) { case LINEJOINT_MITER: break; case LINEJOINT_ROUND: { float radius = width/2; glPushMatrix(); glTranslatef(vert0[0], vert0[1], 0); glBegin(GL_POLYGON); for (int i=0; i <= 360; i += 10) { float radians = -i * DEG2RAD; glVertex2f(cos(radians) * radius, sin(radians) * radius); } glEnd(); glPopMatrix(); glPushMatrix(); glTranslatef(vert1[0], vert1[1], 0); glBegin(GL_POLYGON); for (int i=0; i <= 360; i += 10) { float radians = -i * DEG2RAD; glVertex2f(cos(radians) * radius, sin(radians) * radius); } glEnd(); glPopMatrix(); } break; case LINEJOINT_BEVEL: glBegin(GL_QUADS); glVertex2dv(lastv0); glVertex2d(vert0[0] + butt_dx, vert0[1] - butt_dy); glVertex2dv(lastv1); glVertex2d(vert0[0] - butt_dx, vert0[1] + butt_dy); glVertex2dv(firstv0); glVertex2d(vert1[0] + butt_dx, vert1[1] - butt_dy); glVertex2dv(firstv1); glVertex2d(vert1[0] - butt_dx, vert1[1] + butt_dy); glEnd(); break; default: break; } } else { // draw the linecaps FIXME eventually we just want to draw one, // and only draw the other if this is just a single line seg. switch (linecap) { case LINECAP_BUTT: break; case LINECAP_ROUND: { float radius = width/2; glPushMatrix(); glTranslatef(vert0[0], vert0[1], 0); glBegin(GL_POLYGON); for (int i=0; i <= 360; i += 10) { float radians = -i * DEG2RAD; glVertex2f(cos(radians) * radius, sin(radians) * radius); } glEnd(); glPopMatrix(); glPushMatrix(); glTranslatef(vert1[0], vert1[1], 0); glBegin(GL_POLYGON); for (int i=0; i <= 360; i += 10) { float radians = i * DEG2RAD; glVertex2f(cos(radians) * radius, sin(radians) * radius); } glEnd(); glPopMatrix(); } break; case LINECAP_SQUARE: break; default: break; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -