Index: src/embeddedLua/CMakeLists.txt
===================================================================
--- src/embeddedLua/CMakeLists.txt	(revision 70619)
+++ src/embeddedLua/CMakeLists.txt	(working copy)
@@ -39,6 +39,7 @@
     embeddedlua.cpp
     initbrlcad.cpp
     luadatabase.cpp
+    luahalfspace.cpp
     writestring.cpp
     ../other/lua/src/lapi.c
     ../other/lua/src/lcode.c
Index: src/embeddedLua/initbrlcad.cpp
===================================================================
--- src/embeddedLua/initbrlcad.cpp	(revision 70619)
+++ src/embeddedLua/initbrlcad.cpp	(working copy)
@@ -29,6 +29,7 @@
  */
 
 #include "luadatabase.h"
+#include "luahalfspace.h"
 #include "initbrlcad.h"
 
 
@@ -38,4 +39,5 @@
     BRLCAD::Database& database
 ) {
     InitDatabase(luaState, database);
+    InitHalfspace(luaState);
 }
Index: src/embeddedLua/luadatabase.cpp
===================================================================
--- src/embeddedLua/luadatabase.cpp	(revision 70619)
+++ src/embeddedLua/luadatabase.cpp	(working copy)
@@ -29,6 +29,7 @@
  */
 
 #include <cassert>
+#include <cstring>
 
 #include "luadatabase.h"
 
@@ -116,6 +117,29 @@
 }
 
 
+static int Get
+(
+    lua_State* luaState
+) {
+    Database*   database   = GetDatabase(luaState);
+    const char* objectName = luaL_checkstring(luaState, -1);
+    Object*     object     = database->Get(objectName);
+
+    Object** pObject = static_cast<Object**>(lua_newuserdata(luaState, sizeof(Object*)));
+    *pObject = object;
+
+    if (strcmp(object->Type(), "Halfspace") == 0) {
+        luaL_getmetatable(luaState, "Halfspace");
+        lua_setmetatable(luaState, -2);
+    } else {
+        luaL_getmetatable(luaState, "Object");
+        lua_setmetatable(luaState, -2);
+    }
+
+    return 1;
+}
+
+
 void InitDatabase
 (
     lua_State*        luaState,
@@ -151,6 +175,9 @@
     lua_pushcfunction(luaState, BoundingBoxMaxima);
     lua_setfield(luaState, -2, "BoundingBoxMaxima");
 
+    lua_pushcfunction(luaState, Get);
+    lua_setfield(luaState, -2, "Get");
+
     lua_pop(luaState, 1);
 
     // register a global "database" variable
Index: src/embeddedLua/luahalfspace.cpp
===================================================================
--- src/embeddedLua/luahalfspace.cpp	(nonexistent)
+++ src/embeddedLua/luahalfspace.cpp	(working copy)
@@ -0,0 +1,250 @@
+/*                  L U A H A L F S P A C E . C P P
+ * BRL-CAD
+ *
+ * Copyright (c) 2018 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+/** @file luahalfspace.cpp
+ *
+ *  BRL-CAD embedded lua script:
+ *      BRLCAD::Halfspace functions
+ */
+
+#include <cassert>
+#include <embeddedlua.h>
+
+#include "luahalfspace.h"
+
+
+using namespace BRLCAD;
+
+
+static int NewHalfspace
+(
+    lua_State* luaState
+) {
+    Halfspace** pHalfspace = static_cast<Halfspace**>(lua_newuserdata(luaState, sizeof(Halfspace*)));
+    *pHalfspace = new Halfspace();
+
+    luaL_getmetatable(luaState, "Halfspace");
+    lua_setmetatable(luaState, -2);
+
+    return 1;
+}
+
+
+void InitHalfspaceFactory
+(
+    lua_State* luaState
+) {
+    lua_newtable(luaState);
+    int methodtable = lua_gettop(luaState);
+    luaL_newmetatable(luaState, "HalfspaceFactory");
+    int metatable   = lua_gettop(luaState);
+
+    lua_pushliteral(luaState, "__metatable");
+    lua_pushvalue(luaState, methodtable);
+    lua_settable(luaState, metatable);
+
+    lua_pushliteral(luaState, "__index");
+    lua_pushvalue(luaState, methodtable);
+    lua_settable(luaState, metatable);
+
+    lua_pop(luaState, 1);
+
+    lua_pushcfunction(luaState, NewHalfspace);
+    lua_setfield(luaState, -2, "New");
+
+    lua_pop(luaState, 1);
+
+    lua_newtable(luaState);
+    luaL_getmetatable(luaState, "HalfspaceFactory");
+    lua_setmetatable(luaState, -2);
+    lua_setglobal(luaState, "Halfspace");
+}
+
+
+static Halfspace* GetHalfspace
+(
+    lua_State* luaState
+) {
+    Halfspace** halfspace = static_cast<Halfspace**>(luaL_checkudata(luaState, 1, "Halfspace"));
+
+    assert(halfspace != 0);
+    assert(*halfspace != 0);
+
+    return *halfspace;
+}
+
+
+static int Normal
+(
+    lua_State* luaState
+) {
+    Halfspace* halfspace = GetHalfspace(luaState);
+    Vector3D   normal    = halfspace->Normal();
+
+    lua_pushnumber(luaState, normal.coordinates[0]);
+    lua_pushnumber(luaState, normal.coordinates[1]);
+    lua_pushnumber(luaState, normal.coordinates[2]);
+
+    return 3;
+}
+
+static int SetNormal
+(
+    lua_State* luaState
+) {
+    Halfspace*   halfspace = GetHalfspace(luaState);
+    const double x         = luaL_checknumber(luaState, -3);
+    const double y         = luaL_checknumber(luaState, -2);
+    const double z         = luaL_checknumber(luaState, -1);
+
+    halfspace->SetNormal(Vector3D(x, y, z));
+
+    return 0;
+}
+
+
+static int DistanceFromOrigin
+(
+    lua_State* luaState
+) {
+    Halfspace* halfspace = GetHalfspace(luaState);
+
+    lua_pushnumber(luaState, halfspace->DistanceFromOrigin());
+
+    return 1;
+}
+
+
+static int SetDistanceFromOrigin
+(
+    lua_State* luaState
+) {
+    Halfspace* halfspace  = GetHalfspace(luaState);
+    const double distance = luaL_checknumber(luaState, -1);
+
+    halfspace->SetDistanceFromOrigin(distance);
+
+    return 0;
+}
+
+
+static int Clone
+(
+    lua_State* luaState
+) {
+    Halfspace*  halfspace  = GetHalfspace(luaState);
+    Halfspace** pHalfspace = static_cast<Halfspace**>(lua_newuserdata(luaState, sizeof(Halfspace*)));
+
+    *pHalfspace = static_cast<Halfspace*>(halfspace->Clone());
+
+    luaL_getmetatable(luaState, "Halfspace");
+    lua_setmetatable(luaState, -2);
+
+    return 1;
+}
+
+
+static int ClassName
+(
+    lua_State* luaState
+) {
+    Halfspace* halfspace = GetHalfspace(luaState);
+
+    lua_pushstring(luaState, halfspace->ClassName());
+
+    return 1;
+}
+
+
+static int Type
+(
+    lua_State* luaState
+) {
+    Halfspace* halfspace = GetHalfspace(luaState);
+
+    lua_pushstring(luaState, halfspace->Type());
+
+    return 1;
+}
+
+
+static int IsValid
+(
+    lua_State* luaState
+) {
+    Halfspace* halfspace = GetHalfspace(luaState);
+
+    lua_pushboolean(luaState, halfspace->IsValid());
+
+    return 1;
+}
+
+
+void InitHalfspace
+(
+    lua_State* luaState
+) {
+    lua_newtable(luaState);
+    int methodtable = lua_gettop(luaState);
+    luaL_newmetatable(luaState, "Halfspace");
+    int metatable   = lua_gettop(luaState);
+
+    lua_pushliteral(luaState, "__metatable");
+    lua_pushvalue(luaState, methodtable);
+    lua_settable(luaState, metatable);
+
+    lua_pushliteral(luaState, "__index");
+    lua_pushvalue(luaState, methodtable);
+    lua_settable(luaState, metatable);
+
+    lua_pop(luaState, 1);
+
+    lua_pushcfunction(luaState, Normal);
+    lua_setfield(luaState, -2, "Normal");
+
+    lua_pushcfunction(luaState, SetNormal);
+    lua_setfield(luaState, -2, "SetNormal");
+
+    lua_pushcfunction(luaState, DistanceFromOrigin);
+    lua_setfield(luaState, -2, "DistanceFromOrigin");
+
+    lua_pushcfunction(luaState, SetDistanceFromOrigin);
+    lua_setfield(luaState, -2, "SetDistanceFromOrigin");
+
+    lua_pushcfunction(luaState, Clone);
+    lua_setfield(luaState, -2, "Clone");
+
+    lua_pushcfunction(luaState, ClassName);
+    lua_setfield(luaState, -2, "ClassName");
+
+    lua_pushcfunction(luaState, Type);
+    lua_setfield(luaState, -2, "Type");
+
+    lua_pushcfunction(luaState, IsValid);
+    lua_setfield(luaState, -2, "IsValid");
+
+    lua_pop(luaState, 1);
+
+    InitHalfspaceFactory(luaState);
+}
Index: src/embeddedLua/luahalfspace.h
===================================================================
--- src/embeddedLua/luahalfspace.h	(nonexistent)
+++ src/embeddedLua/luahalfspace.h	(working copy)
@@ -0,0 +1,45 @@
+/*                  L U A H A L F S P A C E . H
+ * BRL-CAD
+ *
+ * Copyright (c) 2018 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+/** @file luahalfspace.h
+ *
+ *  BRL-CAD embedded lua script:
+ *      BRLCAD::Halfspace functions
+ */
+
+#ifndef LUAHALFSPACE_INCLUDED
+#define LUAHALFSPACE_INCLUDED
+
+#include "lua.hpp"
+
+#include "brlcad/Halfspace.h"
+
+
+void InitHalfspace
+(
+    lua_State* luaState
+);
+
+
+#endif // LUAHALFSPACE_INCLUDED
Index: tests/embeddedLua/CMakeLists.txt
===================================================================
--- tests/embeddedLua/CMakeLists.txt	(revision 70619)
+++ tests/embeddedLua/CMakeLists.txt	(working copy)
@@ -41,3 +41,6 @@
 
 add_executable(boundingbox boundingbox.cpp)
 target_link_libraries(boundingbox embeddedlua)
+
+add_executable(halfspace halfspace.cpp)
+target_link_libraries(halfspace embeddedlua)
Index: tests/embeddedLua/halfspace.cpp
===================================================================
--- tests/embeddedLua/halfspace.cpp	(nonexistent)
+++ tests/embeddedLua/halfspace.cpp	(working copy)
@@ -0,0 +1,124 @@
+/*                      H A L F S P A C E . C P P
+ * BRL-CAD
+ *
+ * Copyright (c) 2018 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+/** @file halfspace.cpp
+ *
+ *  BRL-CAD embedded lua script:
+ *      Halfspace test application
+ */
+
+
+#include <iostream>
+#include <sstream>
+
+#include <embeddedlua.h>
+#include <brlcad/MemoryDatabase.h>
+
+
+using namespace BRLCAD;
+
+int main
+(
+    int   argc,
+    char* argv[]
+) {
+    int ret = 0;
+
+    if (argc < 3) {
+        std::cout << "Usage: " << argv[0] << " <BRL-CAD Database> <halfspace object>" << std::endl;
+        ret = 1;
+    }
+    else {
+        try {
+        	std::stringstream TheLuaScript;
+            MemoryDatabase database;
+
+            if (database.Load(argv[1])) {
+                EmbeddedLuaHandle* handle = CreateEmbeddedLuaHandleInstance(database, 0, 0);
+
+                if (handle != 0) {
+                    TheLuaScript
+                        << "h = Halfspace:New()"
+                        << "print(\"Creating new halfspace...\")"
+                        << "print(\"Setting normal to 1, 0, 0...\")"
+                        << "print(\"Setting distance from origin to 100...\")"
+                        << "h:SetNormal(1, 0, 0)"
+                        << "h:SetDistanceFromOrigin(100)"
+                        << "print()"
+
+                        << "print(\"Type: \", h:Type())"
+                        << "print(\"Normal: \", h:Normal())"
+                        << "print(\"DistanceFromOrigin: \", h:DistanceFromOrigin())"
+                        << "print(\"ClassName: \", h:ClassName())"
+                        << "print(\"IsValid: \", h:IsValid())"
+                        << "print()"
+
+                        << "print(\"Selecting object " << argv[2] << " from database...\")"
+                        << "print()"
+
+                        << "database:Select(\"Halfspace.s\")"
+                        << "h = database:Get(\"Halfspace.s\")"
+                        << "print(\"Type: \", h:Type())"
+                        << "print(\"Normal: \", h:Normal())"
+                        << "print(\"DistanceFromOrigin: \", h:DistanceFromOrigin())"
+                        << "print(\"ClassName: \", h:ClassName())"
+                        << "print(\"IsValid: \", h:IsValid())"
+                        << "database:UnSelectAll()"
+                        << "print()"
+
+                        << "print(\"Cloning database object " << argv[2] << "...\")"
+                        << "print()"
+
+                        << "clone = h:Clone()"
+                        << "print(\"Type: \", clone:Type())"
+                        << "print(\"Normal: \", clone:Normal())"
+                        << "print(\"DistanceFromOrigin: \", clone:DistanceFromOrigin())"
+                        << "print(\"ClassName: \", clone:ClassName())"
+                        << "print(\"IsValid: \", clone:IsValid())"
+                        << "print()";
+
+                    handle->Execute(TheLuaScript.str().c_str());
+
+                    std::cout << "Successfully executed all Halfspace functions." << std::endl;
+
+                    DestroyEmbeddedLuaHandleInstance(handle);
+                }
+                else {
+                    std::cerr << "Could not create BRL-CAD embedded Lua handle" << std::endl;
+                    ret = 2;
+                }
+            }
+            else {
+                std::cerr << "Could not load file: " << argv[1] << std::endl;
+                ret = 3;
+            }
+        }
+        catch(BRLCAD::bad_alloc& e) {
+            std::cerr << "Out of memory in: " << e.what() << std::endl;
+            ret = 4;
+        }
+    }
+
+    return ret;
+}
