Version 5 (modified by jaho, 7 years ago) (diff)

--

LAG Developers FAQ

1. What is LAG?
2. What are major components of LAG?
3. How do I edit the GUI?
4. What are LAS files?
5. What do I need to know about laslib?
6. How do I make laslib a shared library?

Why is LAG's code so messy?
How can I make it better?
How do I edit the GUI?
What are LAS files?
What is laslib?
How does Quadtree work?
How does Cacheminder work?
How does loading of files work?
How does saving of files work?
How does rendering work?
What about the LASsaver and LASloader in the quadtree?
What are some major issues with LAG that need work?
What are some additional features that can be added to LAG?
What tools are there to help me with LAG development?
Question X?
Question X?
Question X?
Question X?

1. What is LAG?

LAG stands for LiDAR Analysis GUI. It is a software which provides graphical user interface for processing and visualisation of LiDAR point cloud data. LAG is written in C++ and uses Gtk (gtkmm) for its GUI, and OpenGL for rendering.

2. What are major components of LAG

LAG consist of the main GUI application and a Lidar Quadtree library used for storing and querying the data.

3. How do I edit the GUI?

The GUI layout is stored in lag.ui Glade file which is in plain xml. This allows editing the interface without the need for recompiling the source code every time a change is made. The lag.ui file can be opened in Glade User Interface Designer which can by run with glade-3 command.

The interface of the application is created from xml using Gtk::Builder object, which is instantiated in lag.cpp and then passed by Glib::RefPtr to each of the classes that handle the GUI. All of these classes are located under src/ui folder and each of them has two common methods: void load_xml(builder) and void connect_signals() which are called in their constructors.

The load_xml(const Glib::RefPtr<Gtk::Builder>& builder) method gets widgets from the builder file and assigns them to the class members (pointers). Widgets instantiated by Gtk::Builder have to be deleted manually. In fact, according to documentation, this only applies to top-level widgets (windows and dialogs), but LAG's authors seem to prefer to delete every single one anyway.

The connect_signals() method is responsible for connecting various input signals to class methods. An example lifetime of a Gtk Widget then looks like this:

// Declare a pointer to the widget (as class member)
class MyClass {
  Gtk::Button* my_button;
  void on_my_button_clicked();
}

// Load the widget from xml (in MyClass::load_xml(const Glib::RefPtr<Gtk::Builder>& builder))
builder->get_widget("mybutton", my_button);

// Connect some method to it (in MyClass::connect_signals())
my_button->signal_clicked().connect(sigc::mem_fun(*this, &MyClass::on_my_button_clicked));

// Delete the widget (in the class destructor)
delete my_button;

Modifying the GUI is just as simple as adding new widgets to the Glade file and then handling them in the ui classes.

4. What are LAS files?

LAS is a binary, public file format designed to hold LiDAR point data. An alternative to LAS are ASCII files, which are however much less efficient in terms of both processing time and file size.

LAS files consist of several parts: Public Header Block, Variable Length Records, Point Records and in format 1.3 and later Waveform Records.

A detailed LAS format specification can be found at: http://www.asprs.org/Committee-General/LASer-LAS-File-Format-Exchange-Activities.html

5. What do I need to know about laslib?

Laslib is a library for handling various LiDAR file formats including LAS. LAG makes use of laslib for loading and saving points.

There is no official documentation for laslib API, however it is a fairly well written C++ which provides an easy to use interface. The best way to learn laslib is to study the source code of programs included in lastools.

The main classes of our interest are LASreader and LASwriter. A simple program that reads points from a file, filters out points with classification 7 (noise), prints points' coordinates and then saves them to another file may look like this (note there's no error checking or exception handling for simplicity, but you should always include it the real code):

#include <iostream>
#include "laslib/lasreader.hpp"
#include "laslib/laswriter.hpp"
#include "laslib/lasdefinitions.hpp"

int main(int argc, char** argv)
{
  // Assume that's correct for simplicity
  std::string filename = argv[1];
  std::string file_out = argv[2];

  LASreadOpener lasreadopener;
  LASwriteOpener laswriteopener;
  lasreadopener.set_file_name(filename.c_str());
  laswriteopener.set_file_name(file_out.c_str());

  // Filter out points with classification 7
  std::vecor<char*> filter_args;                 // this simulates a command line arguments for parse() function further down
  filter_args.push_back("filter");               // a dummy first argument
  filter_args.push_back("-drop_classification");
  filter_args.push_back("7");
  filter_args.push_back(0);                      // null termination

  lasreadopener.parse(args.size(), &args[0]);    // &args[0] = *args so we're passing char** args instead of a vector<char*>

  // Declare lasreader
  LASreader* lasreader;

  // Open the file
  lasreader = lasreadopener.open();

  //  Create and open the writer
  LASwriter* laswriter = laswriteopener.open(&lasreader->header);

  // Loop through the points (note they will already be filtered)
  while (lasreader->read_point())
  {
    // Show coordinates
    std::cout << lasreader->point.get_x() << ", " << lareader->point.get_y() << ", " << lasreader->point.get_z() << std::endl;
 
    // Write point
    laswriter->write_point(&lasreader->point);

    // Add it to the inventory (keeps track of min/max values for the header)
    laswriter->update_inventory(&lasreader->point);
  }

  laswriter->update_header(&lasreader->header, TRUE);

  laswriter->close();
  lasreader->close();

  delete laswriter();
  delete lasreader();
}

6. Ho do I make laslib a shared library?

It seems that laslib is mainly developed for Windows users so there are no targets for shared libraries in the Makefiles by default. At the same time shared libraries are needed by LAG to work correctly. To fix this you're going to need to modify the Makefiles and add -fPIC option to the compiler. You'll also have to change the name of the library from laslib to liblaslib for the linker to detect it.

You'll normally find modified Makefiles somewhere around, so you can copy them after downloading a new version of laslib and hopefully they will work. If this is not the case, below is the part that needs to be added to the Makefile inside laslib/src folder.

all: static shared

# these targets set the output directory for the object 
# files and then call make again with the appropriate library targets.  
# This is done so that the fpic flag is set correctly for the library 
# we're building.
static: 
        test -d static || mkdir static
        $(MAKE) liblaslib.a OBJDIR=static

shared:
        test -d shared || mkdir shared
        $(MAKE) liblaslib.so.${VERSION} OBJDIR=shared EXTRA_COPTS=-fPIC

liblaslib.a: ${TARGET_OBJS}
        $(AR) $@ ${TARGET_OBJS}
        cp -p $@ ../lib

liblaslib.so.${VERSION}: ${TARGET_OBJS}
        ${COMPILER} -shared -Wl,-soname,liblaslib.so.1 -o \
        liblaslib.so.${VERSION} ${TARGET_OBJS}
        cp -p $@ ../lib

${TARGET_OBJS}: ${OBJDIR}/%.o: %.cpp
        ${COMPILER} ${BITS} -c ${COPTS} ${EXTRA_COPTS} ${INCLUDE} $< -o $@

You're not likely to have to alter this part and if a newly downloaded version of laslib fails to build with modified Makefiles, the first thing to check is if OBJ_LAS (the list of object files) hasn't changed since the previous release.

Attachments (2)

Download all attachments as: .zip