Jelajahi Sumber

style-guidelines.md

Former-commit-id: 1151a8c5de0c6daba85f79da43ab155497640e88
Alec Jacobson 9 tahun lalu
induk
melakukan
c06cad8bda
1 mengubah file dengan 204 tambahan dan 0 penghapusan
  1. 204 0
      style-guidelines.md

+ 204 - 0
style-guidelines.md

@@ -0,0 +1,204 @@
+# Libigl Style Guidelines
+
+This library is shared by many people. This document highlights some style
+guidelines for _developers_ of the library, but also act as best-practices for
+users.
+
+## One function, one .h/.cpp pair [filefunction]
+
+The structure of libigl is very flat and function-based. For every
+function/sub-routine create a single .h and .cpp file. For example, if you have
+a function that determines connected components from a face list `F` you would
+create the header `connected_components.h` and `connected_components.cpp` and the only
+function defined should be `void connected_components(const ... F, ... C)`. If the
+implementation of `connected_components` requires a subroutine to compute an
+adjacency matrix then _create another pair_ `adjacency_matrix.h` and
+`adjacency_matrix.cpp` with a single function `void adjacency_matrix(const ... F, ...
+A)`.
+
+### Avoid static "helper" functions
+
+Strive to encapsulate sub-functions that could possibly be useful outside of
+the implementation of your current function. This might mean abstracting the
+interface a bit. If it doesn't dramatically effect performance then create a
+new pair of .h/.cpp files with this sub-function.
+
+#### Lambda functions
+
+If encapsulation in a separate file is not possible or does not make sense,
+then avoid crowding the namespace by creating lambda functions within the
+function implmentation.
+
+### Avoid "helper" classes
+
+Libigl is built around the high-performance paradigm of "struct of arrays"
+rather than "array of structs". The way we achieve this is to avoid classes and
+pass "basic types" directly. The price we pay is long function interfaces, but
+this increases code reuse dramatically. A "basic type" in our context is a
+Eigen type, stl type, or basic C type.
+
+
+## Header Documentation
+
+Each function prototype should be well documented in its corresponding .h
+header file. A typical documentation consists of four parts:
+
+```cpp
+// [A human readable description of what the function does.]
+//
+// Inputs:
+//   [variable name of first (const) input]   [dimensions and
+//     description of this input variable]
+//   [variable name of second (const) input]   [dimensions and
+//     description of this input variable]
+//   ...
+// Outputs:
+//   [variable name of first output ]   [dimensions and
+//     description of this output variable]
+//   [variable name of second output ]   [dimensions and
+//     description of this output variable]
+//   ...
+// Returns [description of return value]
+```
+
+### Example
+
+For example the header `barycenter.h`
+
+```
+// Computes the barycenter of every simplex
+//
+// Inputs:
+//   V  #V x dim matrix of vertex coordinates
+//   F  #F x simplex_size  matrix of indices of simplex corners into V
+// Output:
+//   BC  #F x dim matrix of 3d vertices
+//
+```
+
+## Const inputs
+
+All input parameters should be demarcated `const`. If an input is also an
+output than consider exposing two parameters (one `const`) or be sure to list
+the variable under both `// Inputs:` and `// Outputs:` in the header comments.
+
+## Reference parameters
+
+All but simple types should be passed by reference (e.g. `Matrix & mat`) rather
+than pointers (e.g. `Matrix * mat`) or value (e.g. `Matrix mat`).
+
+
+## Returns vs output parameters
+
+All functions should be implemented with at least one overload that has a
+`void` or simple return type (e.g. `bool` on success/failure). With this
+implementation its then possible to write an overload that returns a single
+output.
+
+For example:
+
+```cpp
+template <typename Atype>
+void adjacency_matrix(const ... & F, Eigen::SparseMatrix<AType> & A);
+
+template <typename Atype>
+Eigen::SparseMatrix<Atype> adjacency_matrix(const ... & F);
+```
+
+## Function naming conventions 
+
+Functions (and [thus also files](#filefunction)) should have simple,
+descriptive names using lowercase letters and underscores between words. Avoid
+unnecessary prefaces. For example, instead of `compute_adjacency_matrix`,
+`construct_adjacency_matrix`, `extract_adjacency_matrix`,
+`get_adjacency_matrix`, or `set_adjacency_matrix` just call the function
+`adjacency_matrix`.
+
+## Variable naming conventions
+
+Libigl prefers short (even single character) variable names _with heavy
+documentation_ in the comments in the header file or above the declaration of
+the function. When possible use `V` to mean a list of vertex positions and `F`
+to mean a list of faces/triangles.
+
+## Class naming conventions 
+
+Classes should be avoided. When naming a class use CamelCase (e.g.
+SortableRow.h).
+
+## Enum naming convertion
+
+Enums types should be placed in the appropriate `igl::` namespace and should be
+named in CamelCase (e.g. `igl::SolverStatus`) and instances should be named in
+ALL_CAPS with underscores between words and prefaced with the name of the enum.
+For example:
+
+```cpp
+namespace igl
+{
+  enum SolverStatus
+  {
+    // Good
+    SOLVER_STATUS_CONVERGED = 0,
+    // OK
+    SOLVER_STATUS_MAX_ITER = 1,
+    // Bad
+    SOLVER_STATUS_ERROR = 2,
+    NUM_SOLVER_STATUSES = 3,
+  };
+};
+```
+
+### Exception for file IO
+
+For legacy reasons, file reading and writing functions use a different naming
+convention. A functions reading a `.xyz` file should be named `readXYZ` and a
+function writing `.xyz` files should be names `writeXYZ`.
+
+## `using namespace ...` in global scope
+
+Writing `using namespace std;`, `using namespace Eigen;` etc. outside of a
+global scope is strictly forbidden. Place these lines at the top of each
+function instead.
+
+
+## Namespaces and external dependencies
+
+Functions in the main library (directly in `include/igl`) should only depend on
+Eigen and stl. These functions should have the `igl::` namespace.
+
+Functions with other dependencies should be placed into
+appropriate sub-directories (e.g. if `myfunction` depends on tetgen then create
+`igl/tetgen/myfunction.h` and `igl/tetgen/myfunction.cpp` and give the function
+the namespace `igl::tetgen::myfunction`.
+
+### copyleft subdirectory/namespace 
+
+Dependencies that require users of libigl to release their projects open source
+(e.g. GPL) are considered aggressively "copyleft" and should be placed in the
+`include/igl/copyleft/` sub-directory and `igl::copyleft::` namespace.
+
+## Assertions
+
+Be generous with assertions and always identify the assertion with strings:
+
+```cpp
+assert(m < n && "m must be less than n");
+```
+
+## ifndef include guard
+
+Every header file should be wrapped in an `#ifndef` compiler directive. The
+name of the guard should be in direct correspondence with the path of the .h
+file. For example, `include/igl/tetgen/tetrahedralize.h` should be
+
+```cpp
+#ifndef IGL_TETGEN_TETRAHEDRALIZE_H
+#define IGL_TETGEN_TETRAHEDRALIZE_H
+...
+#endif
+```
+
+## Eigen templates
+
+