Due Thursday, April 14, 11:59 P.M.
- Overview
- Assignment
- Hints
The purpose of this lab is to give you practice using pointers in
Fortran, and to introduce you to dynamic memory allocation.
Top
I have written some code in planars.f90
that implements various routines for manipulating triangulations of planar
surfaces. This code defines a data structure, called a surf,
corresponding to a triangulated surface in the (x,y) plane.
The data structure is organized as follows:
- A vert type contains real variables for its (x,y)
coordinates and a logical variable called flag (used for
bookkeeping).
- The edge type contains two pointers to variables of type
vert.
- The face type contains three pointers to variable of type
edge.
- The surf contains an integer numFaces counting the
number of faces and an array faceList of length numFaces
and type face.
Note that:
- There is only one instance of each edge and vertex in the surface
created in memory. If two edges share a common vertex, they point
to the same vertex, not separate vertices with the same coordinates.
Likewise, faces with edges in common point to a single edge.
- You would normally want to keep a separate list of edges and vertices
for convenience in updating the data. However, leaving out the extra
lists makes for a more useful exercise in understanding pointers and
dynamic data structures.
Make the following modifications to extend the functionality of the code:
- Write a new function called surf_area(s) that takes a
surface s as its parameter and returns the area of the surface.
- Write a new subroutine, rot_surf(s, t) that rotates the
surface s through the angle t about the origin.
- Write a new subroutine, trans_surf(s, x, y) that translates
the surface s by (x, y).
- Write a new function, make_rectangle(u, v) that creates a new
triangulated surface corresponding to the rectangle with opposite vertices
u and v.
- Modify the main program as necessary to test the new functionality.
Top
Each item below corresponds to the task with the same number in the
preceding list.
- Just iterate through each face in the surface, using Heron's formula
(you may copy from here) to determine the area of each triangle. You may
want to write a separate function to calculate the distance between
two vertices. Note that there is no guarantee that the vertices will
be given in any particular order within the edge. E.g. two edges could
both have u pointing at their common vertex, or one could be
using u with the other using v, etc. You will need to
account for this when determining the three distinct vertices for a face.
Use the ASSOCIATED command to check whether the vertex pointers
point to the same vertices.
- First, iterate through each face, setting the flags in all the
vertices in each edge to .FALSE. to indicate that you haven't
moved that vertex yet. Now, iterate through each vertex this way again,
applying the rot_vert subroutine to each vertex and setting the
flags to .TRUE. again as you go along. Make sure you only move
each vertex once by testing the flag as you reach each vertex. Test this
by checking that the points appear to have been mapped correctly in the
main program. As an additional sanity check you may want to verify that
rotating the surface doesn't change its area.
- This one should be easy once you get the last step working. If you've
set things up correctly, you should just be able to copy and paste your
rot_surf function, changing rot to trans
where needed. It would be nice to just write a single subroutine here,
called apply_vert_map, that called a specified subroutine on
every vertex in the surface. If you want to use this approach, go ahead.
However, you will need to either use optional arguments as described in
Chapter 13 of the text or rewrite the interface to the vertex mapping
functions so they take a consistent number of arguments (e.g. a vertex as
the first argument and an assumed-shape array of parameters for the map
as the second argument). If you use the latter approach, you will need
to define an explicit interface to the vertex mapping subroutine using
an interface block inside the surface mapping subroutine. The syntax
for interface blocks is described in Chapter 13.
- You will need to allocate four vertices, five edges, and an array
of two faces. Be sure to allocate the vertices and edges using separate
variables for each face and vertex so the destroy_surf routine
still works correctly. The first four edges should connect the four
pairs of adjacent corners, and the fifth edge should connect any pair of
opposite corners. Now define the edge pointers in the faces so that the
two faces share exactly one edge (the one connecting opposite corners).
You may find it useful to draw a picture here to make sure your faces
refer to the correct edges. When assigning to the member variables
of the edge and face types, remember that you are making a pointer
assignment. So you need to be sure to use => rather than
=. Use the make_triangle function as a model for your
own code.
- One additional test to try is applying the inverse of each of the
mapping functions and checking that the original surface is returned.
You should also test your make_square function using the same
sequence of calls used for the triangle.
Top
Back to the course information page