Is there a simple way to compute whether a plane and a polydata-object intersect?
I want to know on which sides my polydata-object protude my bounding box.
I want to use VTK for this task.
Will the vtkIntersectionPolyDataFilter work for you? http://www.vtk.org/Wiki/VTK/Examples/Cxx/PolyData/IntersectionPolyDataFilter
I solved this using a vtkBoundingBox, which has the plane position and a second vtkBoundingBox which got the the bounds from my vtkPolyData.
You can use vtkCutter, like below:
#include <vtkSmartPointer.h>
#include <vtkCubeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkPlane.h>
#include <vtkCutter.h>
#include <vtkProperty.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
int main(int, char *[])
{
vtkSmartPointer<vtkCubeSource> cube =
vtkSmartPointer<vtkCubeSource>::New();
cube->SetXLength(40);
cube->SetYLength(30);
cube->SetZLength(20);
vtkSmartPointer<vtkPolyDataMapper> cubeMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
cubeMapper->SetInputConnection(cube->GetOutputPort());
// Create a plane to cut,here it cuts in the XZ direction (xz normal=(1,0,0);XY =(0,0,1),YZ =(0,1,0)
vtkSmartPointer<vtkPlane> plane =
vtkSmartPointer<vtkPlane>::New();
plane->SetOrigin(10,0,0);
plane->SetNormal(1,0,0);
// Create cutter
vtkSmartPointer<vtkCutter> cutter =
vtkSmartPointer<vtkCutter>::New();
cutter->SetCutFunction(plane);
cutter->SetInputConnection(cube->GetOutputPort());
cutter->Update();
vtkSmartPointer<vtkPolyDataMapper> cutterMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
cutterMapper->SetInputConnection( cutter->GetOutputPort());
// Create plane actor
vtkSmartPointer<vtkActor> planeActor =
vtkSmartPointer<vtkActor>::New();
planeActor->GetProperty()->SetColor(1.0,1,0);
planeActor->GetProperty()->SetLineWidth(2);
planeActor->SetMapper(cutterMapper);
// Create cube actor
vtkSmartPointer<vtkActor> cubeActor =
vtkSmartPointer<vtkActor>::New();
cubeActor->GetProperty()->SetColor(0.5,1,0.5);
cubeActor->GetProperty()->SetOpacity(0.5);
cubeActor->SetMapper(cubeMapper);
// Create renderers and add actors of plane and cube
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(planeActor); //display the rectangle resulting from the cut
renderer->AddActor(cubeActor); //display the cube
// Add renderer to renderwindow and render
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
renderWindow->SetSize(600, 600);
vtkSmartPointer<vtkRenderWindowInteractor> interactor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor->SetRenderWindow(renderWindow);
renderer->SetBackground(0,0,0);
renderWindow->Render();
interactor->Start();
return EXIT_SUCCESS;
}
Related
I am trying to give a color to the points into a triangulation_3 on CGAL. I just take the example from CGAL describe here
I made a simple modification on this example to be able to draw the triangulation:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h>
#include <CGAL/Delaunay_triangulation_cell_base_3.h>
#include <CGAL/Triangulation_vertex_base_with_info_3.h>
#include <CGAL/IO/Color.h>
#include <CGAL/draw_triangulation_3.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_vertex_base_with_info_3<CGAL::Color, K> Vb;
typedef CGAL::Delaunay_triangulation_cell_base_3<K> Cb;
typedef CGAL::Triangulation_data_structure_3<Vb, Cb> Tds;
typedef CGAL::Delaunay_triangulation_3<K, Tds> Delaunay;
typedef Delaunay::Point Point;
int main()
{
Delaunay T;
T.insert(Point(0,0,0));
T.insert(Point(1,0,0));
T.insert(Point(0,1,0));
T.insert(Point(0,0,1));
T.insert(Point(2,2,2));
T.insert(Point(-1,0,1));
// Set the color of finite vertices of degree 6 to red.
Delaunay::Finite_vertices_iterator vit;
for (Delaunay::Vertex_handle v : T.finite_vertex_handles())
if (T.degree(v) == 6)
v->info() = CGAL::Color(0,255,0);
CGAL::draw(T);
return 0;
}
But no matter which color I put on v->info() = CGAL::Color(0,255,0); the method draw always give the same red points in the window displayed:
I understand that the code is constructing a data structure that contains color information but this could be independent of the draw method, so i think that the window doesn't show me green points because this is not the way to color the points. If so, what is the way to get a triangulation with green points using the draw method?'.
In its current form, the viewer is not able to change the color of vertices nor edges.
But it is easy to change the code.
Copy the file draw_triangulation_3.h in your project
edit the method void compute_vertex(Vertex_const_handle vh), (line 92 in this file) to use the add_point method with a color as parameter: add_point(vh->point(), vh->info());
I've got another question.
Here is my code:
#include <iostream>
#include <osg/Light>
#include <osg/LightSource>
#include <osg/PositionAttitudeTransform>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
int main(int argc, char** argv)
{
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile("cube.3ds"); //importing object
osg::ref_ptr<osg::StateSet> ss = loadedModel->getOrCreateStateSet();
osg::ref_ptr<osg::Image> image = osgDB::readImageFile("box_1.png"); //loading texture from file
osg::ref_ptr<osg::Texture2D> tex(new osg::Texture2D()); /creating texture for model from image
tex->setImage(image);
ss->setTextureAttributeAndModes(0, tex);
osg::ref_ptr<osg::TexGen> texGen(new osg::TexGen());
texGen->setPlane(osg::TexGen::S, osg::Plane(0.075, 0.0, 0.0, 0.5));
texGen->setPlane(osg::TexGen::T, osg::Plane(0.0, 0.035, 0.0, 0.3));
ss->setTextureAttributeAndModes(0, texGen);
osgViewer::Viewer viewer; //Creating viewer
viewer.setSceneData(loadedModel);
viewer.setUpViewOnSingleScreen(0);
return viewer.run();
}
So what this code is doing: It takes model from file (i.e. "cube.3s") and adding texture (image from file "box_1.png" to it. You can change texture on object by switching one image to another. But here is a question: He stretching image on whole model. How it can be done just by placing all image on each face of model (they are platonic solid (like pyramid, cube and etc.)).
This all boils down to the texture coordinates that were assigned to the model's vertices when it was built. If you convert cube.3ds to .OSG or .OSGT text format you can see the UV coordinates that the texture mapper uses to determine where in the texture map to look for each corner of each face. This is how textures are "pinned" to faces.
Just load and edit that cube or pyramid in a 3d modeling tool and fix up the UV coordinates to what you want.
Alternately, you could edit the .osgt file to change the UV coordinates assigned to each vertex.
I have imported object (Cube) from 3dsMax in my OSG project in VisualStudio. But I can't find out how to make transparent only one face of this imported cube. this is my code:
#include <osgViewer/Viewer>
#include <iostream>
#include <osg/Group>
#include <osg/Node>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osg/Notify>
#include <osg/MatrixTransform>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/StateSet>
#include <osg/StateAttribute>
#include <osg/CullFace>
#include <osg/Point>
#include <osg/Light>
#include <osg/LightSource>
#include <osg/BlendFunc>
#include <osg/Material>
#include <osg/PolygonMode>
int main(int argc, char** argv)
{
osg::ref_ptr<osg::Group> root = new osg::Group;
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("cube.3ds"); //Importing model
osg::StateSet* state2 = model->getOrCreateStateSet(); //Creating material
osg::ref_ptr<osg::Material> mat2 = new osg::Material;
mat2->setAlpha(osg::Material::FRONT_AND_BACK, 0.1); //Making alpha channel
state2->setAttributeAndModes( mat2.get() ,
osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
osg::BlendFunc* bf = new //Blending
osg::BlendFunc(osg::BlendFunc::SRC_ALPHA,
osg::BlendFunc::ONE_MINUS_DST_COLOR );
state2->setAttributeAndModes(bf);
root->addChild(model.get());
osgViewer::Viewer viewer;
viewer.setSceneData(root.get());
viewer.setUpViewOnSingleScreen(0);
return viewer.run();
}
This is my source with just imported file. I've tried implement transparency with multiple passes but have no success.
Is there any method how could i make it ?
The code in the question does make the model transparent. For example, with the cessna model from the OSG data package:
Adding two more models, a box and a sphere, where the box also has blending:
We see that blending is working. If you add another model but it isn't displayed, then probably the plane is being rendered before the other models. If the plane happens to be in front of the other models, even if the plane is transparent, you won't see them; as they don't pass the depth test.
Adding
cessna->getStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
cessna->getStateSet()->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
forces the cessna to be rendered after the opaque models.
Also, note that if you provide a blending function, then you don't need to call
cessna->getStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
Let's see another scene, where the box is behind the plane and we haven't set the rendering hint:
And now with the rendering hint active:
My idea is simple:
given a vtk polydata and a vtk plane, get two diferent polydata. This polydatas are the division of the original polydata.
Here's one half of a sphere. Flip the plane over (negate the normal) to get the other half.
#include "vtkActor.h"
#include "vtkClipPolyData.h"
#include "vtkPlane.h"
#include "vtkInteractorObserver.h"
#include "vtkInteractorStyleSwitch.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkSphereSource.h"
using namespace std;
int main(int argc, char ** argv) {
vtkSmartPointer<vtkSphereSource> sphere =
vtkSmartPointer<vtkSphereSource>::New();
vtkSmartPointer<vtkClipPolyData> clip =
vtkSmartPointer<vtkClipPolyData>::New();
clip->SetValue(0);
clip->GenerateClippedOutputOn();
clip->SetInputConnection(sphere->GetOutputPort());
vtkSmartPointer<vtkPlane> plane =
vtkSmartPointer<vtkPlane>::New();
//plane->SetNormal(-1.0, 0.0, 0.0);
plane->SetNormal(1.0, 0.0, 0.0);
clip->SetClipFunction (plane);
vtkSmartPointer<vtkPolyDataMapper> polyDataMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
polyDataMapper->SetInputConnection(clip->GetOutputPort());
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(polyDataMapper);
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(800,600);
renderWindow->SetWindowName("VTK");
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(actor);
renderWindow->AddRenderer(renderer);
vtkInteractorStyleSwitch * styleSwitch
= vtkInteractorStyleSwitch::SafeDownCast(
renderWindowInteractor->GetInteractorStyle());
if (styleSwitch)
styleSwitch->SetCurrentStyleToTrackballCamera();
renderWindow->Render();
renderWindowInteractor->Start();
}
CMakeLists.txt :
cmake_minimum_required(VERSION 2.6)
project(V)
set(VTK_DIR "VTK_DIR-NOTFOUND"
CACHE PATH "location of VTK libraries" )
set(CMAKE_BUILD_TYPE debug)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
add_executable(clip clip.cxx)
target_link_libraries(clip ${VTK_LIBRARIES})
I want to move my GTK_WINDOW across the screen automatically. Currently I have it in a draw/move loop, but that's terribly choppy. I'm very new to GTK programming (and gui programming in general). What am I missing?
You haven't said what sort of path you want the window to follow. If the path is some simple function of time -- that is, if you have a way to compute where you want the window to be at any given time -- you could try the method illustrated in following code. For the quite-simple menu in the example, it works ok on my Linux system and produces fairly smooth motion.
The key to the method is that instead of moving the window a given distance per timer event, it finds out the current time and moves the window to the location it should be at, at that time. Thus, the time derivative of speed of motion should be constant, which avoids ragged or choppy motion even if timer events occur irregularly. (As noted in g-timeout-add() description, irregularity can easily occur.)
In this example, the path is from top left of window to bottom left and back, repeatedly. The constant 'HalfTime' in timerEvent() controls how long it takes to move from corner to corner. The constant 3 in the g_timeout_add() call sets the timer interval to 0.003 seconds, or about 333 moves per second (MPS). (You may want to try more-reasonable rates, such as 20, 30, 40, etc MPS; I used the number 3 because I didn't look up g-timeout-add() before using it, and assumed the delay was hundreths of seconds, for about 33 MPS, rather than milliseconds, for about 333 MPS.) If your window contents are quite complex, fewer MPS will be practical. Also, I tried some slower rates and got more of an impression of choppiness.
/* $Id: app12.c $
Re: animating position of a top-level Gtk window
jiw July 2011 -- Offered without warranty under GPL v3
terms per http://www.gnu.org/licenses/gpl.html */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <gtk/gtk.h>
typedef struct DATA { GTimer *timer; GtkWidget *window; int w, h; }
DataStruct;
gboolean timerEvent(void *dataset) {
enum { HalfTime=8, CycTime=2*HalfTime };
gulong micros;
DataStruct *data =dataset;
double t = fabs(fmod (g_timer_elapsed (data->timer, µs), CycTime));
int x = (t*data->w)/HalfTime, y = (t*data->h)/HalfTime;
gtk_window_move (GTK_WINDOW(data->window),
t<HalfTime? x : 2*data->w-x, t<HalfTime? y : 2*data->h-y);
return TRUE; /* Keep timeout running */
}
int main(int argc, char **argv) {
GtkWidget *vbox, *b;
GdkScreen *gds;
DataStruct data;
data.timer = g_timer_new();
gtk_init (&argc, &argv);
data.window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW(data.window), 200, 150);
g_signal_connect (G_OBJECT(data.window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER(data.window), vbox);
b = gtk_button_new_with_label ("Click to Exit");
gtk_box_pack_start (GTK_BOX(vbox), b, TRUE, TRUE, TRUE);
g_signal_connect (b, "clicked", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all (data.window);
gds = gdk_screen_get_default (); /* Get pointer to screen */
data.w = gdk_screen_get_width (gds); /* Find out screen width */
data.h = gdk_screen_get_height (gds); /* Find out screen height */
printf ("Screen size = %d by %d\n", data.w, data.h); fflush(stdout);
g_timeout_add(3, timerEvent, &data); /* Create .003 sec timer */
gtk_main();
return (0);
}