File Exchange

image thumbnail

"boundary" class v2.1: a wrapper for surface objects

version 1.2.0.0 (15.9 KB) by Kenneth Eaton
Adds functionality for fast detection of intersections between line segments and rendered surfaces

1 Download

Updated 25 Nov 2008

View License

MOTIVATION:

I have been working on an updated version of the game "Staker" that I posted to the FEX. This is an artillery warfare game inspired by Scorched Earth, so it involved plotting the trajectory of projectiles and detecting when they have struck a surface. In the first version, I checked for a surface intersection by simply using interp2 to find the height of the ground beneath the projectile, and an impact occurred when this height was greater than or equal to the height of the projectile.

There were two limitations with using interp2: 1) it could be slow, and I was limited in what I could render and 2) the interpolated surface doesn't generally match the surface as it is graphically rendered. MATLAB renders a surface using a series of triangular facets, and I wanted the projectiles to interact with the graphical rendering of the surface.

I wanted to use SURFACE (not PATCH) so that I could do texture mapping, so I set about finding ways to create an alternative triangular representation of the rendered surface, and then creating a ray-triangle intersection algorithm to detect collisions between a line segment and any triangular facet of the surface. To speed things up I had to precompute a number of variables for the algorithm.

I had much success, and now had an algorithm that worked much faster and gave accurate interactions between the projectile and the rendered surface. However, the interface was clunky; I had to share triangular surface representations and precomputed variables across a number of functions, and these had to be updated every time the surface object was modified.

To make things more modular and easier to manage, I therefore created this "boundary" object class, which stores the precomputed variables, handles their updating, contains the ray-triangle intersection code, and affords a simpler interface that mimics a surface object (with added functionality, of course). I've included part of the help below; you should type 'help boundary' for more thorough information.

p.s. I know this could probably be done in a nicer way using the newer OOP syntax (and the "handle" class), but I am still working in MATLAB 7.1.

USAGE:

OBJ = BOUNDARY(HAXES,'PropertyName',PropertyValue,...) creates a wrapper for surface objects that adds functionality for fast detection of intersections between a line segment and the triangular facets of the rendered surface object. BOUNDARY is designed to be used in place of calls to SURFACE, and OBJ is an object with reference behavior designed to mimic a surface object handle (although it cannot be returned by FINDOBJ). HAXES should be a valid axes handle, followed by parameter/value pairs (or any valid format used by the SET command). This input list must contain at a minimum one of the following sets of parameters:

-'XData', 'YData', and 'ZData': This will add a surface object to axes HAXES. Any other properties specified should be valid surface object properties.
-'Faces' and 'Vertices': This will add a patch object to axes HAXES. The 'Faces' property must be N-by-3 (i.e. triangular patches). Any other properties specified should be valid patch object properties.

OBJ = BOUNDARY(HOBJECT,...) creates a boundary object given the handle HOBJECT of a valid surface or patch object. As above, the 'Faces' property of the patch object must be N-by-3 (i.e. triangular patches). HOBJECT can be followed by additional parameter/value pairs.

Objects of class boundary have an additional overloaded method: INTERSECT. This method computes the [x y z] coordinates of the point where a user-defined line segment intersects the rendered surface. Type 'help boundary/intersect' for complete information about the INTERSECT method.

The object properties 'Faces' and 'Vertices', which are normal properties for patch objects, can be accessed using the GET command for boundary objects, even if they were created from surface objects. Objects of class boundary also have three additional properties that control their behavior: 'Alignment', 'AutoUpdate', and 'IndexFcn'. Type 'help boundary' for complete information about how to use these properties and for more examples.

Example: Interpolate a curve along a rendered surface (compared to interp2 results).

[X,Y] = meshgrid(1:3);
Z = [0 0 0; 0 1 0; 0 0 0];
hSurface = surface(X,Y,Z);
hSurface = boundary(hSurface); % Example of converting a handle
hold on;
axis equal;
x = (1:0.1:3).';
y = 4-x;
pointArray = intersect(hSurface,[x y 2.*ones(size(x))],[0 0 -3]);
pointArray = vertcat(pointArray{:});
z = pointArray(:,3);
line(x,y,z,'Color','r'); % INTERSECT-derived curve
line(x,y,interp2(X,Y,Z,x,y),'Color','g'); % INTERP2-derived curve
view(-39,13);

Cite As

Kenneth Eaton (2020). "boundary" class v2.1: a wrapper for surface objects (https://www.mathworks.com/matlabcentral/fileexchange/20637-boundary-class-v2-1-a-wrapper-for-surface-objects), MATLAB Central File Exchange. Retrieved .

Comments and Ratings (4)

Mikhail

Nice! In R2017a, with Example 2 (line and surface intersection), the Paul's diff below needs to be expanded:

case {'double','matlab.graphics.primitive.Patch','matlab.graphics.axis.Axes'}

Paul

Thanks for this fantastic piece of code!

In Matlab 2015b (at least) the patch object seem to have changed slightly. This diff fixed the issue:

Index: boundary.m
===================================================================
--- boundary.m (revision 4590)
+++ boundary.m (revision 4591)
@@ -321,8 +321,9 @@
end

%====================================================================
- case 'double', % Input object is of class 'double'; it must be
- % checked to see if it is a valid handle object
+ case {'double','matlab.graphics.primitive.Patch'}, % Input object is
+ % of class 'double' or 'Patch' (Matlab 2015b); it
+ % must bechecked to see if it is a valid handle object

if ishandle(hObject),
handleType = get(hObject,'Type');

Paul

Kenneth Eaton

Just a quick head's up for anyone unfamiliar with class directories... the unzipped folder '@boundary' should not be placed on the MATLAB path, but should be placed in another folder that is on the MATLAB path.

Updates

1.2.0.0

Fixed a bug with the SET command

1.1.0.0

-Multiple line segment input to INTERSECT.
-New options for INTERSECT ('-first'/'-last'/'-all').
-Added new 'Alignment' property for BOUNDARY objects.
-Corrected automatic selection of triangle orientation/alignment.

MATLAB Release Compatibility
Created with R14SP3
Compatible with any release
Platform Compatibility
Windows macOS Linux
Acknowledgements

Inspired by: Staker v0.6