Math 171 Spring 2005, Lab 16 (double lab)

Due Thursday, April 14, 11:59 P.M.

  1. Overview
  2. Assignment
  3. Hints

Overview

The purpose of this lab is to give you practice using pointers in Fortran, and to introduce you to dynamic memory allocation.

Top

Assignment

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:

  1. A vert type contains real variables for its (x,y) coordinates and a logical variable called flag (used for bookkeeping).
  2. The edge type contains two pointers to variables of type vert.
  3. The face type contains three pointers to variable of type edge.
  4. The surf contains an integer numFaces counting the number of faces and an array faceList of length numFaces and type face.

Note that:

Make the following modifications to extend the functionality of the code:

  1. Write a new function called surf_area(s) that takes a surface s as its parameter and returns the area of the surface.
  2. Write a new subroutine, rot_surf(s, t) that rotates the surface s through the angle t about the origin.
  3. Write a new subroutine, trans_surf(s, x, y) that translates the surface s by (x, y).
  4. Write a new function, make_rectangle(u, v) that creates a new triangulated surface corresponding to the rectangle with opposite vertices u and v.
  5. Modify the main program as necessary to test the new functionality.

Top

Hints

Each item below corresponds to the task with the same number in the preceding list.

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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