Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4b2caf33d3 | |||
|
|
7b77b268bf | ||
|
|
910f991734 | ||
|
|
a55fdbfd0f | ||
|
|
0dd1f1b293 | ||
|
|
dc7a19c2f3 | ||
|
|
04ec4b3d2d | ||
|
|
68ff8f6921 | ||
|
|
499c7d91d8 |
2
README.md
Normal file
2
README.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# Dimensional Doors legacy mirror
|
||||||
|
This repository is a mirror of the legacy github repo for dimensional doors, its mostly just for a sort of lost media search to get all of the old versions of the mod built.
|
||||||
@@ -21,7 +21,6 @@ public class CommonProxy implements IGuiHandler
|
|||||||
public static String WARP_PNG = "/WARP.png";
|
public static String WARP_PNG = "/WARP.png";
|
||||||
|
|
||||||
public void registerRenderers()
|
public void registerRenderers()
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
public void registerEntity(Class <? extends Entity > entity, String entityname, int id, Object mod, int trackingrange, int updateFreq, boolean updatevelo)
|
public void registerEntity(Class <? extends Entity > entity, String entityname, int id, Object mod, int trackingrange, int updateFreq, boolean updatevelo)
|
||||||
|
|||||||
@@ -307,111 +307,28 @@ public class BlockRift extends Block implements ITileEntityProvider
|
|||||||
@Override
|
@Override
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
|
|
||||||
public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random rand)
|
public void randomDisplayTick(World world, int x, int y, int z, Random rand)
|
||||||
{
|
{
|
||||||
|
|
||||||
int count;
|
|
||||||
//growth in the direction towards the nearby rift
|
|
||||||
float xGrowth=0;
|
|
||||||
float yGrowth=0;
|
|
||||||
float zGrowth=0;
|
|
||||||
//growth away from the nearby rift
|
|
||||||
float xGrowthn=0;
|
|
||||||
float yGrowthn=0;
|
|
||||||
float zGrowthn=0;
|
|
||||||
//how far the particles are away from original rift. Used to decrease noise the farther they are away.
|
|
||||||
float xChange = 0;
|
|
||||||
float yChange = 0;
|
|
||||||
float zChange = 0;
|
|
||||||
|
|
||||||
TileEntityRift tile = (TileEntityRift)par1World.getBlockTileEntity(par2, par3, par4);
|
ArrayList<Point3D> targets=findReachableBlocks(world, x, y, z, 2, false);
|
||||||
|
|
||||||
float Xoffset=0;
|
|
||||||
float Yoffset=0;
|
|
||||||
float Zoffset=0;
|
|
||||||
for (count = 0; count < 12 && tile!=null; ++count)
|
|
||||||
{
|
|
||||||
//TODO change to a switch statement for clarity
|
|
||||||
if(tile.xOffset>0)
|
|
||||||
{
|
|
||||||
if(rand.nextInt(tile.xOffset)==0)
|
|
||||||
{
|
|
||||||
xGrowth =xGrowth+.15F*tile.xOffset;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(tile.xOffset<0)
|
|
||||||
{
|
|
||||||
if(rand.nextInt(-tile.xOffset)==0)
|
|
||||||
{
|
|
||||||
xGrowthn =xGrowthn-.15F*-tile.xOffset;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tile.yOffset>0)
|
|
||||||
{
|
|
||||||
if(rand.nextInt(tile.yOffset)==0)
|
|
||||||
{
|
|
||||||
yGrowth =yGrowth+.15F*tile.yOffset;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(tile.yOffset<0)
|
|
||||||
{
|
|
||||||
if(rand.nextInt(-tile.yOffset)==0)
|
|
||||||
{
|
|
||||||
yGrowthn =yGrowthn-.15F*-tile.yOffset;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tile.zOffset>0)
|
|
||||||
{
|
|
||||||
if(rand.nextInt(tile.zOffset)==0)
|
|
||||||
{
|
|
||||||
zGrowth =zGrowth+.15F*tile.zOffset;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(tile.zOffset<0)
|
|
||||||
{
|
|
||||||
if(rand.nextInt(-tile.zOffset)==0)
|
|
||||||
{
|
|
||||||
zGrowthn =zGrowthn-.15F*-tile.zOffset;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
xChange=(float) ((xGrowth+xGrowthn)+rand.nextGaussian()*.05F);
|
TileEntityRift tile = (TileEntityRift)world.getBlockTileEntity(x, y, z);
|
||||||
yChange=(float) ((yGrowth+yGrowthn)+rand.nextGaussian()*.05F);
|
|
||||||
zChange=(float) ((zGrowth+zGrowthn)+rand.nextGaussian()*.05F);
|
|
||||||
|
|
||||||
Xoffset= ((0.25F/(1+Math.abs(xChange))));
|
|
||||||
|
|
||||||
Yoffset= ((0.25F/(1+Math.abs(yChange))));
|
|
||||||
Zoffset= ((0.25F/(1+Math.abs(zChange))));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FMLClientHandler.instance().getClient().effectRenderer.addEffect(new RiftFX(par1World,par2+.5+xChange+Xoffset*rand.nextGaussian(), par3+.5+yChange+Yoffset*rand.nextGaussian() , par4+.5+zChange+Zoffset*rand.nextGaussian(), rand.nextGaussian() * 0.001D, rand.nextGaussian() * 0.001D, rand.nextGaussian() * 0.001D, FMLClientHandler.instance().getClient().effectRenderer));
|
|
||||||
FMLClientHandler.instance().getClient().effectRenderer.addEffect(new RiftFX(par1World,par2+.5-xChange-Xoffset*rand.nextGaussian(), par3+.5-yChange-Yoffset*rand.nextGaussian() , par4+.5-zChange-Zoffset*rand.nextGaussian(), rand.nextGaussian() * 0.001D, rand.nextGaussian() * 0.001D, rand.nextGaussian() * 0.001D, FMLClientHandler.instance().getClient().effectRenderer));
|
|
||||||
|
|
||||||
|
|
||||||
if(rand.nextBoolean())
|
if(rand.nextBoolean())
|
||||||
{
|
{
|
||||||
//renders an extra little blob on top of the actual rift location so its easier to find. Eventually will only render if the player has the goggles.
|
//renders an extra little blob on top of the actual rift location so its easier to find. Eventually will only render if the player has the goggles.
|
||||||
FMLClientHandler.instance().getClient().effectRenderer.addEffect(new GoggleRiftFX(par1World,par2+.5, par3+.5, par4+.5, rand.nextGaussian() * 0.01D, rand.nextGaussian() * 0.01D, rand.nextGaussian() * 0.01D, FMLClientHandler.instance().getClient().effectRenderer));
|
FMLClientHandler.instance().getClient().effectRenderer.addEffect(new GoggleRiftFX(world,x+.5, y+.5, z+.5, rand.nextGaussian() * 0.01D, rand.nextGaussian() * 0.01D, rand.nextGaussian() * 0.01D, FMLClientHandler.instance().getClient().effectRenderer));
|
||||||
}
|
}
|
||||||
if(tile.shouldClose)
|
if(tile.shouldClose)
|
||||||
{
|
{
|
||||||
//renders an opposite color effect if it is being closed by the rift remover
|
//renders an opposite color effect if it is being closed by the rift remover
|
||||||
FMLClientHandler.instance().getClient().effectRenderer.addEffect(new ClosingRiftFX(par1World,par2+.5, par3+.5, par4+.5, rand.nextGaussian() * 0.01D, rand.nextGaussian() * 0.01D, rand.nextGaussian() * 0.01D, FMLClientHandler.instance().getClient().effectRenderer));
|
FMLClientHandler.instance().getClient().effectRenderer.addEffect(new ClosingRiftFX(world,x+.5, y+.5, z+.5, rand.nextGaussian() * 0.01D, rand.nextGaussian() * 0.01D, rand.nextGaussian() * 0.01D, FMLClientHandler.instance().getClient().effectRenderer));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean tryPlacingRift(World world, int x, int y, int z)
|
public boolean tryPlacingRift(World world, int x, int y, int z)
|
||||||
|
|||||||
@@ -29,21 +29,25 @@ import cpw.mods.fml.relauncher.Side;
|
|||||||
import cpw.mods.fml.relauncher.SideOnly;
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class regulates all the operations involving the storage and manipulation of dimensions.
|
* This class regulates all the operations involving the storage and
|
||||||
* It handles saving dim data, teleporting the player, and creating/registering new dimensions as
|
* manipulation of dimensions. It handles saving dim data, teleporting the
|
||||||
* well as loading old dimensions on startup
|
* player, and creating/registering new dimensions as well as loading old
|
||||||
|
* dimensions on startup
|
||||||
*/
|
*/
|
||||||
public class PocketManager
|
public class PocketManager
|
||||||
{
|
{
|
||||||
private static class InnerDimData extends NewDimData
|
private static class InnerDimData extends NewDimData
|
||||||
{
|
{
|
||||||
// This class allows us to instantiate NewDimData indirectly without exposing
|
// This class allows us to instantiate NewDimData indirectly without
|
||||||
// a public constructor from NewDimData. It's meant to stop us from constructing
|
// exposing
|
||||||
// instances of NewDimData going through PocketManager. In turn, that enforces
|
// a public constructor from NewDimData. It's meant to stop us from
|
||||||
// that any link destinations must be real dimensions controlled by PocketManager.
|
// constructing
|
||||||
|
// instances of NewDimData going through PocketManager. In turn, that
|
||||||
|
// enforces
|
||||||
|
// that any link destinations must be real dimensions controlled by
|
||||||
|
// PocketManager.
|
||||||
|
|
||||||
public InnerDimData(int id, InnerDimData parent, DimensionType type,
|
public InnerDimData(int id, InnerDimData parent, DimensionType type, IUpdateWatcher<ClientLinkData> linkWatcher)
|
||||||
IUpdateWatcher<ClientLinkData> linkWatcher)
|
|
||||||
{
|
{
|
||||||
super(id, parent, type, linkWatcher);
|
super(id, parent, type, linkWatcher);
|
||||||
}
|
}
|
||||||
@@ -80,7 +84,7 @@ public class PocketManager
|
|||||||
Point4D source = link.point;
|
Point4D source = link.point;
|
||||||
NewDimData dimension = getDimensionData(source.getDimension());
|
NewDimData dimension = getDimensionData(source.getDimension());
|
||||||
DimLink dLink = dimension.getLink(source);
|
DimLink dLink = dimension.getLink(source);
|
||||||
dLink.lock=link.lock;
|
dLink.lock = link.lock;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,9 +112,12 @@ public class PocketManager
|
|||||||
|
|
||||||
private static class DimRegistrationCallback implements IDimRegistrationCallback
|
private static class DimRegistrationCallback implements IDimRegistrationCallback
|
||||||
{
|
{
|
||||||
// We use this class to provide Compactor with the ability to send us dim data without
|
// We use this class to provide Compactor with the ability to send us
|
||||||
// having to instantiate a bunch of data containers and without exposing an "unsafe"
|
// dim data without
|
||||||
// creation method for anyone to call. Integrity protection for the win! It's like
|
// having to instantiate a bunch of data containers and without exposing
|
||||||
|
// an "unsafe"
|
||||||
|
// creation method for anyone to call. Integrity protection for the win!
|
||||||
|
// It's like
|
||||||
// exposing a private constructor ONLY to a very specific trusted class.
|
// exposing a private constructor ONLY to a very specific trusted class.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -133,12 +140,14 @@ public class PocketManager
|
|||||||
private static final UpdateWatcherProxy<ClientDimData> dimWatcher = new UpdateWatcherProxy<ClientDimData>();
|
private static final UpdateWatcherProxy<ClientDimData> dimWatcher = new UpdateWatcherProxy<ClientDimData>();
|
||||||
private static ArrayList<NewDimData> rootDimensions = null;
|
private static ArrayList<NewDimData> rootDimensions = null;
|
||||||
|
|
||||||
//HashMap that maps all the dimension IDs registered with DimDoors to their DD data.
|
// HashMap that maps all the dimension IDs registered with DimDoors to their
|
||||||
|
// DD data.
|
||||||
private static HashMap<Integer, InnerDimData> dimensionData = null;
|
private static HashMap<Integer, InnerDimData> dimensionData = null;
|
||||||
//ArrayList that stores the dimension IDs of any dimension that has been deleted.
|
// ArrayList that stores the dimension IDs of any dimension that has been
|
||||||
|
// deleted.
|
||||||
private static ArrayList<Integer> dimensionIDBlackList = null;
|
private static ArrayList<Integer> dimensionIDBlackList = null;
|
||||||
|
|
||||||
//Stores all the personal pocket mappings
|
// Stores all the personal pocket mappings
|
||||||
private static HashMap<String, NewDimData> personalPocketsMapping = null;
|
private static HashMap<String, NewDimData> personalPocketsMapping = null;
|
||||||
|
|
||||||
public static boolean isLoaded()
|
public static boolean isLoaded()
|
||||||
@@ -147,7 +156,9 @@ public class PocketManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* simple method called on startup to register all dims saved in the dim list. Only tries to register pocket dims, though. Also calls load()
|
* simple method called on startup to register all dims saved in the dim
|
||||||
|
* list. Only tries to register pocket dims, though. Also calls load()
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static void load()
|
public static void load()
|
||||||
@@ -167,23 +178,21 @@ public class PocketManager
|
|||||||
dimensionIDBlackList = new ArrayList<Integer>();
|
dimensionIDBlackList = new ArrayList<Integer>();
|
||||||
personalPocketsMapping = new HashMap<String, NewDimData>();
|
personalPocketsMapping = new HashMap<String, NewDimData>();
|
||||||
|
|
||||||
|
if (FMLCommonHandler.instance().getEffectiveSide().isClient())
|
||||||
if(FMLCommonHandler.instance().getEffectiveSide().isClient())
|
|
||||||
{
|
{
|
||||||
//Shouldnt try to load everything if we are a client
|
// Shouldnt try to load everything if we are a client
|
||||||
//This was preventing onPacket from loading properly
|
// This was preventing onPacket from loading properly
|
||||||
isLoading=false;
|
isLoading = false;
|
||||||
isLoaded=true;
|
isLoaded = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//Register Limbo
|
// Register Limbo
|
||||||
DDProperties properties = DDProperties.instance();
|
DDProperties properties = DDProperties.instance();
|
||||||
registerDimension(properties.LimboDimensionID, null, DimensionType.ROOT);
|
registerDimension(properties.LimboDimensionID, null, DimensionType.ROOT);
|
||||||
|
|
||||||
|
|
||||||
loadInternal();
|
loadInternal();
|
||||||
|
|
||||||
//Register pocket dimensions
|
// Register pocket dimensions
|
||||||
registerPockets(properties);
|
registerPockets(properties);
|
||||||
|
|
||||||
isLoaded = true;
|
isLoaded = true;
|
||||||
@@ -194,33 +203,34 @@ public class PocketManager
|
|||||||
{
|
{
|
||||||
InnerDimData dimData;
|
InnerDimData dimData;
|
||||||
DimensionType type = DimensionType.getTypeFromIndex(packedData.DimensionType);
|
DimensionType type = DimensionType.getTypeFromIndex(packedData.DimensionType);
|
||||||
if(type == null)
|
if (type == null)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Invalid dimension type");
|
throw new IllegalArgumentException("Invalid dimension type");
|
||||||
}
|
}
|
||||||
//register roots
|
// register roots
|
||||||
if(packedData.ID==packedData.ParentID)
|
if (packedData.ID == packedData.ParentID)
|
||||||
{
|
{
|
||||||
dimData = new InnerDimData(packedData.ID, null, type, linkWatcher);
|
dimData = new InnerDimData(packedData.ID, null, type, linkWatcher);
|
||||||
dimData.root=dimData;
|
dimData.root = dimData;
|
||||||
dimData.parent=dimData;
|
dimData.parent = dimData;
|
||||||
dimData.depth=packedData.Depth;
|
dimData.depth = packedData.Depth;
|
||||||
dimData.isFilled=packedData.IsFilled;
|
dimData.isFilled = packedData.IsFilled;
|
||||||
dimData.origin = new Point4D(packedData.Origin.getX(),packedData.Origin.getY(),packedData.Origin.getZ(),packedData.ID);
|
dimData.origin = new Point4D(packedData.Origin.getX(), packedData.Origin.getY(), packedData.Origin.getZ(), packedData.ID);
|
||||||
|
|
||||||
PocketManager.rootDimensions.add(dimData);
|
PocketManager.rootDimensions.add(dimData);
|
||||||
}
|
}
|
||||||
else //register children
|
else
|
||||||
|
// register children
|
||||||
{
|
{
|
||||||
InnerDimData test = PocketManager.dimensionData.get(packedData.ParentID);
|
InnerDimData test = PocketManager.dimensionData.get(packedData.ParentID);
|
||||||
dimData = new InnerDimData(packedData.ID, test, type, linkWatcher);
|
dimData = new InnerDimData(packedData.ID, test, type, linkWatcher);
|
||||||
dimData.isFilled=packedData.IsFilled;
|
dimData.isFilled = packedData.IsFilled;
|
||||||
dimData.origin = new Point4D(packedData.Origin.getX(),packedData.Origin.getY(),packedData.Origin.getZ(),packedData.ID);
|
dimData.origin = new Point4D(packedData.Origin.getX(), packedData.Origin.getY(), packedData.Origin.getZ(), packedData.ID);
|
||||||
dimData.root = PocketManager.createDimensionData(packedData.RootID);
|
dimData.root = PocketManager.createDimensionData(packedData.RootID);
|
||||||
|
|
||||||
if(packedData.DungeonData!=null)
|
if (packedData.DungeonData != null)
|
||||||
{
|
{
|
||||||
dimData.dungeon=DDSaveHandler.unpackDungeonData(packedData.DungeonData);
|
dimData.dungeon = DDSaveHandler.unpackDungeonData(packedData.DungeonData);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -232,8 +242,10 @@ public class PocketManager
|
|||||||
|
|
||||||
public static boolean deletePocket(NewDimData target, boolean deleteFolder)
|
public static boolean deletePocket(NewDimData target, boolean deleteFolder)
|
||||||
{
|
{
|
||||||
// We can't delete the dimension if it's currently loaded or if it's not actually a pocket.
|
// We can't delete the dimension if it's currently loaded or if it's not
|
||||||
// We cast to InnerDimData so that if anyone tries to be a smartass and create their
|
// actually a pocket.
|
||||||
|
// We cast to InnerDimData so that if anyone tries to be a smartass and
|
||||||
|
// create their
|
||||||
// own version of NewDimData, this will throw an exception.
|
// own version of NewDimData, this will throw an exception.
|
||||||
InnerDimData dimension = (InnerDimData) target;
|
InnerDimData dimension = (InnerDimData) target;
|
||||||
if (dimension.isPocketDimension() && DimensionManager.getWorld(dimension.id()) == null)
|
if (dimension.isPocketDimension() && DimensionManager.getWorld(dimension.id()) == null)
|
||||||
@@ -292,7 +304,7 @@ public class PocketManager
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(personalPocketsMapping.containsValue(dimension))
|
if (personalPocketsMapping.containsValue(dimension))
|
||||||
{
|
{
|
||||||
DimensionManager.registerDimension(dimension.id(), properties.PersonalPocketProviderID);
|
DimensionManager.registerDimension(dimension.id(), properties.PersonalPocketProviderID);
|
||||||
}
|
}
|
||||||
@@ -303,7 +315,8 @@ public class PocketManager
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
System.err.println("Could not register pocket dimension #" + dimension.id() + ". Probably caused by a version update/save data corruption/other mods.");
|
System.err.println("Could not register pocket dimension #" + dimension.id()
|
||||||
|
+ ". Probably caused by a version update/save data corruption/other mods.");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -327,7 +340,7 @@ public class PocketManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(Integer dimID : dimensionIDBlackList)
|
for (Integer dimID : dimensionIDBlackList)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -342,30 +355,31 @@ public class PocketManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* loads the dim data from the saved hashMap. Also handles compatibility with old saves, see OldSaveHandler
|
* loads the dim data from the saved hashMap. Also handles compatibility
|
||||||
|
* with old saves, see OldSaveHandler
|
||||||
*/
|
*/
|
||||||
private static void loadInternal()
|
private static void loadInternal()
|
||||||
{
|
{
|
||||||
File saveDir = DimensionManager.getCurrentSaveRootDirectory();
|
File saveDir = DimensionManager.getCurrentSaveRootDirectory();
|
||||||
if (saveDir != null)
|
if (saveDir != null)
|
||||||
{
|
{
|
||||||
//Try to import data from old DD versions
|
// Try to import data from old DD versions
|
||||||
//TODO - remove this code in a few versions
|
// TODO - remove this code in a few versions
|
||||||
File oldSaveData = new File(saveDir+"/DimensionalDoorsData");
|
File oldSaveData = new File(saveDir + "/DimensionalDoorsData");
|
||||||
if(oldSaveData.exists())
|
if (oldSaveData.exists())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
System.out.println("Importing old DD save data...");
|
System.out.println("Importing old DD save data...");
|
||||||
OldSaveImporter.importOldSave(oldSaveData);
|
OldSaveImporter.importOldSave(oldSaveData);
|
||||||
|
|
||||||
oldSaveData.renameTo(new File(oldSaveData.getAbsolutePath()+"_IMPORTED"));
|
oldSaveData.renameTo(new File(oldSaveData.getAbsolutePath() + "_IMPORTED"));
|
||||||
|
|
||||||
System.out.println("Import Succesful!");
|
System.out.println("Import Succesful!");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
//TODO handle fail cases
|
// TODO handle fail cases
|
||||||
System.out.println("Import failed!");
|
System.out.println("Import failed!");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -387,7 +401,7 @@ public class PocketManager
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//Check this last to make sure we set the flag shortly after.
|
// Check this last to make sure we set the flag shortly after.
|
||||||
if (isSaving)
|
if (isSaving)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -439,6 +453,7 @@ public class PocketManager
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* method to register a new pocket with DD and with forge.
|
* method to register a new pocket with DD and with forge.
|
||||||
|
*
|
||||||
* @param parent
|
* @param parent
|
||||||
* @param type
|
* @param type
|
||||||
* @param playername
|
* @param playername
|
||||||
@@ -454,10 +469,10 @@ public class PocketManager
|
|||||||
DDProperties properties = DDProperties.instance();
|
DDProperties properties = DDProperties.instance();
|
||||||
int dimensionID = DimensionManager.getNextFreeDimId();
|
int dimensionID = DimensionManager.getNextFreeDimId();
|
||||||
|
|
||||||
//register a personal pocket
|
// register a personal pocket
|
||||||
if(type == DimensionType.PERSONAL)
|
if (type == DimensionType.PERSONAL)
|
||||||
{
|
{
|
||||||
if(playername == null)
|
if (playername == null)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("A personal pocket must be attached to a playername");
|
throw new IllegalArgumentException("A personal pocket must be attached to a playername");
|
||||||
}
|
}
|
||||||
@@ -467,15 +482,16 @@ public class PocketManager
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ //register a pocket as personal if its parents are personal, but without a mapping.
|
{ // register a pocket as personal if its parents are personal, but
|
||||||
if(parent.type == DimensionType.PERSONAL)
|
// without a mapping.
|
||||||
|
if (parent.type == DimensionType.PERSONAL)
|
||||||
{
|
{
|
||||||
DimensionManager.registerDimension(dimensionID, properties.PersonalPocketProviderID);
|
DimensionManager.registerDimension(dimensionID, properties.PersonalPocketProviderID);
|
||||||
NewDimData data = registerDimension(dimensionID, (InnerDimData) parent, DimensionType.PERSONAL);
|
NewDimData data = registerDimension(dimensionID, (InnerDimData) parent, DimensionType.PERSONAL);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//register a standard pocket
|
// register a standard pocket
|
||||||
DimensionManager.registerDimension(dimensionID, properties.PocketProviderID);
|
DimensionManager.registerDimension(dimensionID, properties.PocketProviderID);
|
||||||
return registerDimension(dimensionID, (InnerDimData) parent, type);
|
return registerDimension(dimensionID, (InnerDimData) parent, type);
|
||||||
}
|
}
|
||||||
@@ -489,6 +505,7 @@ public class PocketManager
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a dimension with DD but NOT with forge.
|
* Registers a dimension with DD but NOT with forge.
|
||||||
|
*
|
||||||
* @param dimensionID
|
* @param dimensionID
|
||||||
* @param parent
|
* @param parent
|
||||||
* @param isPocket
|
* @param isPocket
|
||||||
@@ -499,7 +516,7 @@ public class PocketManager
|
|||||||
{
|
{
|
||||||
if (dimensionData.containsKey(dimensionID))
|
if (dimensionData.containsKey(dimensionID))
|
||||||
{
|
{
|
||||||
if(PocketManager.dimensionIDBlackList.contains(dimensionID))
|
if (PocketManager.dimensionIDBlackList.contains(dimensionID))
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Cannot register a dimension with ID = " + dimensionID + " because it has been blacklisted.");
|
throw new IllegalArgumentException("Cannot register a dimension with ID = " + dimensionID + " because it has been blacklisted.");
|
||||||
}
|
}
|
||||||
@@ -524,7 +541,8 @@ public class PocketManager
|
|||||||
// client side. createDimensionData() always handles root dimensions
|
// client side. createDimensionData() always handles root dimensions
|
||||||
// properly, even if they weren't defined before.
|
// properly, even if they weren't defined before.
|
||||||
|
|
||||||
// SenseiKiwi: I'm a little worried about how createDimensionData will raise
|
// SenseiKiwi: I'm a little worried about how createDimensionData will
|
||||||
|
// raise
|
||||||
// an event when it creates any root dimensions... Needs checking later.
|
// an event when it creates any root dimensions... Needs checking later.
|
||||||
|
|
||||||
InnerDimData root = (InnerDimData) createDimensionData(rootID);
|
InnerDimData root = (InnerDimData) createDimensionData(rootID);
|
||||||
@@ -545,11 +563,14 @@ public class PocketManager
|
|||||||
}
|
}
|
||||||
if (dimension.isPocketDimension() && !DimensionManager.isDimensionRegistered(dimension.id()))
|
if (dimension.isPocketDimension() && !DimensionManager.isDimensionRegistered(dimension.id()))
|
||||||
{
|
{
|
||||||
//Im registering pocket dims here. I *think* we can assume that if its a pocket and we are
|
// Im registering pocket dims here. I *think* we can assume that if
|
||||||
//registering its dim data, we also need to register it with forge.
|
// its a pocket and we are
|
||||||
|
// registering its dim data, we also need to register it with forge.
|
||||||
|
|
||||||
//New packet stuff prevents this from always being true, unfortuantly. I send the dimdata to the client when they teleport.
|
// New packet stuff prevents this from always being true,
|
||||||
//Steven
|
// unfortuantly. I send the dimdata to the client when they
|
||||||
|
// teleport.
|
||||||
|
// Steven
|
||||||
DimensionManager.registerDimension(dimensionID, mod_pocketDim.properties.PocketProviderID);
|
DimensionManager.registerDimension(dimensionID, mod_pocketDim.properties.PocketProviderID);
|
||||||
}
|
}
|
||||||
return dimension;
|
return dimension;
|
||||||
@@ -572,15 +593,19 @@ public class PocketManager
|
|||||||
|
|
||||||
public static NewDimData createDimensionDataDangerously(int dimensionID)
|
public static NewDimData createDimensionDataDangerously(int dimensionID)
|
||||||
{
|
{
|
||||||
// Same as createDimensionData(int), but public. Meant to discourage anyone from
|
// Same as createDimensionData(int), but public. Meant to discourage
|
||||||
// using it unless absolutely needed! We'll probably phase this out eventually.
|
// anyone from
|
||||||
|
// using it unless absolutely needed! We'll probably phase this out
|
||||||
|
// eventually.
|
||||||
return createDimensionData(dimensionID);
|
return createDimensionData(dimensionID);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static NewDimData createDimensionData(int dimensionID)
|
protected static NewDimData createDimensionData(int dimensionID)
|
||||||
{
|
{
|
||||||
// Retrieve the data for a dimension. If we don't have a record for that dimension,
|
// Retrieve the data for a dimension. If we don't have a record for that
|
||||||
// assume it's a non-pocket dimension that hasn't been initialized with us before
|
// dimension,
|
||||||
|
// assume it's a non-pocket dimension that hasn't been initialized with
|
||||||
|
// us before
|
||||||
// and create a NewDimData instance for it.
|
// and create a NewDimData instance for it.
|
||||||
NewDimData dimension = PocketManager.dimensionData.get(dimensionID);
|
NewDimData dimension = PocketManager.dimensionData.get(dimensionID);
|
||||||
|
|
||||||
@@ -643,10 +668,12 @@ public class PocketManager
|
|||||||
{
|
{
|
||||||
return PocketManager.dimensionIDBlackList.contains(dimensionID);
|
return PocketManager.dimensionIDBlackList.contains(dimensionID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void registerDimWatcher(IUpdateWatcher<ClientDimData> watcher)
|
public static void registerDimWatcher(IUpdateWatcher<ClientDimData> watcher)
|
||||||
{
|
{
|
||||||
getDimwatcher().registerReceiver(watcher);
|
getDimwatcher().registerReceiver(watcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean unregisterDimWatcher(IUpdateWatcher<ClientDimData> watcher)
|
public static boolean unregisterDimWatcher(IUpdateWatcher<ClientDimData> watcher)
|
||||||
{
|
{
|
||||||
return getDimwatcher().unregisterReceiver(watcher);
|
return getDimwatcher().unregisterReceiver(watcher);
|
||||||
@@ -669,7 +696,8 @@ public class PocketManager
|
|||||||
|
|
||||||
public static void writePacket(DataOutputStream output) throws IOException
|
public static void writePacket(DataOutputStream output) throws IOException
|
||||||
{
|
{
|
||||||
// Write a very compact description of our dimensions and links to be sent to a client
|
// Write a very compact description of our dimensions and links to be
|
||||||
|
// sent to a client
|
||||||
Compactor.write(dimensionData.values(), output);
|
Compactor.write(dimensionData.values(), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -680,16 +708,17 @@ public class PocketManager
|
|||||||
|
|
||||||
public static void createAndRegisterBlacklist(List<Integer> blacklist)
|
public static void createAndRegisterBlacklist(List<Integer> blacklist)
|
||||||
{
|
{
|
||||||
//TODO - create a special blacklist provider
|
// TODO - create a special blacklist provider
|
||||||
for(Integer dimID : blacklist)
|
for (Integer dimID : blacklist)
|
||||||
{
|
{
|
||||||
PocketManager.dimensionIDBlackList.add(dimID);
|
PocketManager.dimensionIDBlackList.add(dimID);
|
||||||
DimensionManager.registerDimension(dimID, DDProperties.instance().PocketProviderID);
|
DimensionManager.registerDimension(dimID, DDProperties.instance().PocketProviderID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void readPacket(DataInputStream input) throws IOException
|
public static void readPacket(DataInputStream input) throws IOException
|
||||||
{
|
{
|
||||||
//TODO- figure out why this is getting called so frequently
|
// TODO- figure out why this is getting called so frequently
|
||||||
if (isLoaded)
|
if (isLoaded)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -719,7 +748,7 @@ public class PocketManager
|
|||||||
|
|
||||||
public static NewDimData getPersonalDimensionForPlayer(String name)
|
public static NewDimData getPersonalDimensionForPlayer(String name)
|
||||||
{
|
{
|
||||||
if(personalPocketsMapping.containsKey(name))
|
if (personalPocketsMapping.containsKey(name))
|
||||||
{
|
{
|
||||||
return personalPocketsMapping.get(name);
|
return personalPocketsMapping.get(name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ import StevenDimDoors.mod_pocketDim.tileentities.TileEntityDimDoor;
|
|||||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityDimDoorGold;
|
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityDimDoorGold;
|
||||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityRift;
|
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityRift;
|
||||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityTransTrapdoor;
|
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityTransTrapdoor;
|
||||||
|
import StevenDimDoors.mod_pocketDim.util.l_systems.LSystem;
|
||||||
import StevenDimDoors.mod_pocketDim.world.BiomeGenLimbo;
|
import StevenDimDoors.mod_pocketDim.world.BiomeGenLimbo;
|
||||||
import StevenDimDoors.mod_pocketDim.world.BiomeGenPocket;
|
import StevenDimDoors.mod_pocketDim.world.BiomeGenPocket;
|
||||||
import StevenDimDoors.mod_pocketDim.world.DDBiomeGenBase;
|
import StevenDimDoors.mod_pocketDim.world.DDBiomeGenBase;
|
||||||
@@ -325,6 +326,36 @@ public class mod_pocketDim
|
|||||||
DDLoot.registerInfo(properties);
|
DDLoot.registerInfo(properties);
|
||||||
proxy.loadTextures();
|
proxy.loadTextures();
|
||||||
proxy.registerRenderers();
|
proxy.registerRenderers();
|
||||||
|
|
||||||
|
LSystem.generateLSystem("terdragon", LSystem.TERDRAGON, 4);
|
||||||
|
LSystem.generateLSystem("terdragon", LSystem.TERDRAGON, 5);
|
||||||
|
// LSystem.generateLSystem("terdragon", LSystem.TERDRAGON, 6); //degenerate
|
||||||
|
LSystem.generateLSystem("terdragon", LSystem.TERDRAGON, 7);
|
||||||
|
// LSystem.generateLSystem("terdragon", LSystem.TERDRAGON, 8);
|
||||||
|
// LSystem.generateLSystem("terdragon", LSystem.TERDRAGON, 9);
|
||||||
|
|
||||||
|
|
||||||
|
// LSystem.generateLSystem("vortex", LSystem.VORTEX, 8);
|
||||||
|
LSystem.generateLSystem("vortex", LSystem.VORTEX, 9);
|
||||||
|
LSystem.generateLSystem("vortex", LSystem.VORTEX, 10);
|
||||||
|
LSystem.generateLSystem("vortex", LSystem.VORTEX, 11);
|
||||||
|
// LSystem.generateLSystem("vortex", LSystem.VORTEX, 12);
|
||||||
|
|
||||||
|
LSystem.generateLSystem("twindragon", LSystem.TWINDRAGON, 7);
|
||||||
|
LSystem.generateLSystem("twindragon", LSystem.TWINDRAGON, 8);
|
||||||
|
LSystem.generateLSystem("twindragon", LSystem.TWINDRAGON, 9);
|
||||||
|
LSystem.generateLSystem("twindragon", LSystem.TWINDRAGON, 10);
|
||||||
|
// LSystem.generateLSystem("twindragon", LSystem.TWINDRAGON, 11);
|
||||||
|
|
||||||
|
|
||||||
|
LSystem.generateLSystem("dragon", LSystem.DRAGON, 8);
|
||||||
|
LSystem.generateLSystem("dragon", LSystem.DRAGON, 9);
|
||||||
|
LSystem.generateLSystem("dragon", LSystem.DRAGON, 10);
|
||||||
|
LSystem.generateLSystem("dragon", LSystem.DRAGON, 11);
|
||||||
|
// LSystem.generateLSystem("dragon", LSystem.DRAGON, 12);
|
||||||
|
// LSystem.generateLSystem("dragon", LSystem.DRAGON, 13);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
|
|||||||
@@ -18,14 +18,21 @@ import com.google.gson.stream.JsonReader;
|
|||||||
|
|
||||||
public class DimDataProcessor extends BaseConfigurationProcessor<PackedDimData>
|
public class DimDataProcessor extends BaseConfigurationProcessor<PackedDimData>
|
||||||
{
|
{
|
||||||
|
//The name of the version ID where it is stored in the JSON
|
||||||
public final String JSON_VERSION_PROPERTY_NAME = "SAVE_DATA_VERSION_ID_INSTANCE";
|
public final String JSON_VERSION_PROPERTY_NAME = "SAVE_DATA_VERSION_ID_INSTANCE";
|
||||||
|
|
||||||
|
//mapping of version IDs to their corresponding schema. Prevents reloading of schema during save/load cycles
|
||||||
private HashMap<Integer, JsonObject> SAVE_DATA_SCHEMA;
|
private HashMap<Integer, JsonObject> SAVE_DATA_SCHEMA;
|
||||||
|
|
||||||
|
//The parser used to read in the JSON Files
|
||||||
private static final JsonParser jsonParser = new JsonParser();
|
private static final JsonParser jsonParser = new JsonParser();
|
||||||
|
|
||||||
|
//The directory for JSON schema files
|
||||||
public static final String BASE_SCHEMA_PATH = "/assets/dimdoors/text/";
|
public static final String BASE_SCHEMA_PATH = "/assets/dimdoors/text/";
|
||||||
|
|
||||||
|
/**
|
||||||
//TODO dont load the schemas every time
|
* Need to manually include a schema defintion for every save file version currently supported
|
||||||
|
*/
|
||||||
public DimDataProcessor()
|
public DimDataProcessor()
|
||||||
{
|
{
|
||||||
SAVE_DATA_SCHEMA = new HashMap<Integer, JsonObject>();
|
SAVE_DATA_SCHEMA = new HashMap<Integer, JsonObject>();
|
||||||
@@ -33,7 +40,7 @@ public class DimDataProcessor extends BaseConfigurationProcessor<PackedDimData>
|
|||||||
//Load the old schema/s
|
//Load the old schema/s
|
||||||
SAVE_DATA_SCHEMA.put(982405775, loadSchema(BASE_SCHEMA_PATH+"Dim_Data_Schema_v982405775.json"));
|
SAVE_DATA_SCHEMA.put(982405775, loadSchema(BASE_SCHEMA_PATH+"Dim_Data_Schema_v982405775.json"));
|
||||||
|
|
||||||
//load the current schema
|
//load the schema representing the current save data format
|
||||||
SAVE_DATA_SCHEMA.put(PackedDimData.SAVE_DATA_VERSION_ID, loadSchema(BASE_SCHEMA_PATH+"Dim_Data_Schema_v1-0-0.json"));
|
SAVE_DATA_SCHEMA.put(PackedDimData.SAVE_DATA_VERSION_ID, loadSchema(BASE_SCHEMA_PATH+"Dim_Data_Schema_v1-0-0.json"));
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -159,7 +166,18 @@ public class DimDataProcessor extends BaseConfigurationProcessor<PackedDimData>
|
|||||||
*/
|
*/
|
||||||
public JsonObject processSaveData(JsonObject schema, JsonObject save)
|
public JsonObject processSaveData(JsonObject schema, JsonObject save)
|
||||||
{
|
{
|
||||||
if(save.get(JSON_VERSION_PROPERTY_NAME).getAsInt()== 982405775)
|
int incomingSaveVersionID = save.get(JSON_VERSION_PROPERTY_NAME).getAsInt();
|
||||||
|
|
||||||
|
// Handle save data versions that are current
|
||||||
|
if(incomingSaveVersionID == PackedDimData.SAVE_DATA_VERSION_ID)
|
||||||
|
{
|
||||||
|
JSONValidator.validate(this.getSaveDataSchema(save), save);
|
||||||
|
return save;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle save data versions that are older, starting with the random one.
|
||||||
|
// We have to
|
||||||
|
if(incomingSaveVersionID== 982405775)
|
||||||
{
|
{
|
||||||
DimensionType type;
|
DimensionType type;
|
||||||
|
|
||||||
@@ -183,11 +201,11 @@ public class DimDataProcessor extends BaseConfigurationProcessor<PackedDimData>
|
|||||||
save.remove("IsDungeon");
|
save.remove("IsDungeon");
|
||||||
save.addProperty("DimensionType",type.index);
|
save.addProperty("DimensionType",type.index);
|
||||||
save.remove(this.JSON_VERSION_PROPERTY_NAME);
|
save.remove(this.JSON_VERSION_PROPERTY_NAME);
|
||||||
save.addProperty(this.JSON_VERSION_PROPERTY_NAME, PackedDimData.SAVE_DATA_VERSION_ID);
|
|
||||||
return processSaveData(this.getSaveDataSchema(save), save);
|
//Need to hardcode the version number here, so if we change the current version then this still updates to the proper version
|
||||||
|
save.addProperty(this.JSON_VERSION_PROPERTY_NAME, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONValidator.validate(this.getSaveDataSchema(save), save);
|
return processSaveData(this.getSaveDataSchema(save), save);
|
||||||
return save;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package StevenDimDoors.mod_pocketDim.tileentities;
|
package StevenDimDoors.mod_pocketDim.tileentities;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.monster.EntityEnderman;
|
import net.minecraft.entity.monster.EntityEnderman;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
@@ -11,6 +11,7 @@ import net.minecraft.network.INetworkManager;
|
|||||||
import net.minecraft.network.packet.Packet;
|
import net.minecraft.network.packet.Packet;
|
||||||
import net.minecraft.network.packet.Packet132TileEntityData;
|
import net.minecraft.network.packet.Packet132TileEntityData;
|
||||||
import net.minecraft.util.AxisAlignedBB;
|
import net.minecraft.util.AxisAlignedBB;
|
||||||
|
import net.minecraft.util.MathHelper;
|
||||||
import StevenDimDoors.mod_pocketDim.ServerPacketHandler;
|
import StevenDimDoors.mod_pocketDim.ServerPacketHandler;
|
||||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||||
import StevenDimDoors.mod_pocketDim.config.DDProperties;
|
import StevenDimDoors.mod_pocketDim.config.DDProperties;
|
||||||
@@ -18,6 +19,8 @@ import StevenDimDoors.mod_pocketDim.core.DimLink;
|
|||||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||||
|
import StevenDimDoors.mod_pocketDim.util.l_systems.LSystem;
|
||||||
|
import StevenDimDoors.mod_pocketDim.util.l_systems.LSystem.PolygonStorage;
|
||||||
import StevenDimDoors.mod_pocketDim.watcher.ClientLinkData;
|
import StevenDimDoors.mod_pocketDim.watcher.ClientLinkData;
|
||||||
|
|
||||||
public class TileEntityRift extends DDTileEntityBase
|
public class TileEntityRift extends DDTileEntityBase
|
||||||
@@ -45,11 +48,16 @@ public class TileEntityRift extends DDTileEntityBase
|
|||||||
public Point4D nearestRiftLocation = null;
|
public Point4D nearestRiftLocation = null;
|
||||||
public int spawnedEndermenID = 0;
|
public int spawnedEndermenID = 0;
|
||||||
|
|
||||||
|
public int riftRotation = random.nextInt(360);
|
||||||
|
public int renderKey = random.nextInt(LSystem.curves.size());
|
||||||
|
public float growth = 0;
|
||||||
|
|
||||||
public TileEntityRift()
|
public TileEntityRift()
|
||||||
{
|
{
|
||||||
// Vary the update times of rifts to prevent all the rifts in a cluster
|
// Vary the update times of rifts to prevent all the rifts in a cluster
|
||||||
// from updating at the same time.
|
// from updating at the same time.
|
||||||
updateTimer = random.nextInt(UPDATE_PERIOD);
|
updateTimer = random.nextInt(UPDATE_PERIOD);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -74,6 +82,7 @@ public class TileEntityRift extends DDTileEntityBase
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check if this rift should render white closing particles and
|
// Check if this rift should render white closing particles and
|
||||||
// spread the closing effect to other rifts nearby.
|
// spread the closing effect to other rifts nearby.
|
||||||
if (shouldClose)
|
if (shouldClose)
|
||||||
@@ -92,6 +101,7 @@ public class TileEntityRift extends DDTileEntityBase
|
|||||||
updateNearestRift();
|
updateNearestRift();
|
||||||
spread(mod_pocketDim.properties);
|
spread(mod_pocketDim.properties);
|
||||||
}
|
}
|
||||||
|
growth += 1F/(growth+1);
|
||||||
updateTimer++;
|
updateTimer++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +149,7 @@ public class TileEntityRift extends DDTileEntityBase
|
|||||||
private void closeRift()
|
private void closeRift()
|
||||||
{
|
{
|
||||||
NewDimData dimension = PocketManager.createDimensionData(worldObj);
|
NewDimData dimension = PocketManager.createDimensionData(worldObj);
|
||||||
if (closeTimer == CLOSING_PERIOD / 2)
|
if (growth < CLOSING_PERIOD / 2)
|
||||||
{
|
{
|
||||||
for (DimLink riftLink : dimension.findRiftsInRange(worldObj, 6, xCoord, yCoord, zCoord))
|
for (DimLink riftLink : dimension.findRiftsInRange(worldObj, 6, xCoord, yCoord, zCoord))
|
||||||
{
|
{
|
||||||
@@ -152,7 +162,7 @@ public class TileEntityRift extends DDTileEntityBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (closeTimer >= CLOSING_PERIOD && !worldObj.isRemote)
|
if (growth == 0 && !worldObj.isRemote)
|
||||||
{
|
{
|
||||||
DimLink link = PocketManager.getLink(this.xCoord, this.yCoord, this.zCoord, worldObj);
|
DimLink link = PocketManager.getLink(this.xCoord, this.yCoord, this.zCoord, worldObj);
|
||||||
if (link != null)
|
if (link != null)
|
||||||
@@ -162,7 +172,8 @@ public class TileEntityRift extends DDTileEntityBase
|
|||||||
worldObj.setBlockToAir(xCoord, yCoord, zCoord);
|
worldObj.setBlockToAir(xCoord, yCoord, zCoord);
|
||||||
worldObj.playSound(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5, "mods.DimDoors.sfx.riftClose", 0.7f, 1, false);
|
worldObj.playSound(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5, "mods.DimDoors.sfx.riftClose", 0.7f, 1, false);
|
||||||
}
|
}
|
||||||
closeTimer++;
|
|
||||||
|
growth --;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean updateNearestRift()
|
public boolean updateNearestRift()
|
||||||
@@ -251,6 +262,10 @@ public class TileEntityRift extends DDTileEntityBase
|
|||||||
this.zOffset = nbt.getInteger("zOffset");
|
this.zOffset = nbt.getInteger("zOffset");
|
||||||
this.shouldClose = nbt.getBoolean("shouldClose");
|
this.shouldClose = nbt.getBoolean("shouldClose");
|
||||||
this.spawnedEndermenID = nbt.getInteger("spawnedEndermenID");
|
this.spawnedEndermenID = nbt.getInteger("spawnedEndermenID");
|
||||||
|
this.riftRotation = nbt.getInteger("riftRotation");
|
||||||
|
this.renderKey = nbt.getInteger("renderKey");
|
||||||
|
this.growth = nbt.getFloat("growth");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -263,6 +278,10 @@ public class TileEntityRift extends DDTileEntityBase
|
|||||||
nbt.setInteger("zOffset", this.zOffset);
|
nbt.setInteger("zOffset", this.zOffset);
|
||||||
nbt.setBoolean("shouldClose", this.shouldClose);
|
nbt.setBoolean("shouldClose", this.shouldClose);
|
||||||
nbt.setInteger("spawnedEndermenID", this.spawnedEndermenID);
|
nbt.setInteger("spawnedEndermenID", this.spawnedEndermenID);
|
||||||
|
nbt.setInteger("renderKey", this.renderKey);
|
||||||
|
nbt.setInteger("riftRotation", this.riftRotation);
|
||||||
|
nbt.setFloat("growth", this.growth);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -286,4 +305,11 @@ public class TileEntityRift extends DDTileEntityBase
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PolygonStorage getCurve()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
return (LSystem.curves.get(renderKey));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,557 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.util.l_systems;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import org.poly2tri.Poly2Tri;
|
||||||
|
import org.poly2tri.geometry.polygon.Polygon;
|
||||||
|
import org.poly2tri.geometry.polygon.PolygonPoint;
|
||||||
|
import org.poly2tri.triangulation.TriangulationPoint;
|
||||||
|
import org.poly2tri.triangulation.delaunay.DelaunayTriangle;
|
||||||
|
|
||||||
|
|
||||||
|
public class LSystem
|
||||||
|
{
|
||||||
|
public static ArrayList<PolygonStorage> curves = new ArrayList<PolygonStorage>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array containing the args to generate a curve.
|
||||||
|
* index 0 = rules
|
||||||
|
* index 1 = angle
|
||||||
|
* index 2 = start string
|
||||||
|
*/
|
||||||
|
public static final String[] TERDRAGON = {"F>+F----F++++F-","60","F"};
|
||||||
|
public static final String[] DRAGON = {"X>X+YF:Y>FX-Y","90","FX"};
|
||||||
|
public static final String[] TWINDRAGON = {"X>X+YF:Y>FX-Y","90","FX--FX"};
|
||||||
|
public static final String[] VORTEX = {"X>X+YF:Y>FX-Y","90","FX---FX"};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a fractal curve
|
||||||
|
* @param args: 0 = rules, 1 = angle, 2 = start
|
||||||
|
* @param steps
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static void generateLSystem(String key, String[] args, int steps)
|
||||||
|
{
|
||||||
|
//Parse the rules from the first index
|
||||||
|
String[] rules = args[0].split(":");
|
||||||
|
HashMap<String, String> lSystemsRule = new HashMap<String, String>();
|
||||||
|
|
||||||
|
for (String rule : rules)
|
||||||
|
{
|
||||||
|
String[] parts = rule.split(">");
|
||||||
|
lSystemsRule.put(parts[0], parts[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the angle for each turn
|
||||||
|
int angle = Integer.parseInt(args[1]);
|
||||||
|
|
||||||
|
|
||||||
|
//String to hold the output
|
||||||
|
//Initialize with starting string
|
||||||
|
String output = args[2];
|
||||||
|
|
||||||
|
//generate the l-system
|
||||||
|
output = (generate(args[2], steps, lSystemsRule));
|
||||||
|
|
||||||
|
//get the boundary of the polygon
|
||||||
|
PolygonStorage polygon = getBoundary(convertToPoints(angle, output, (steps)));
|
||||||
|
|
||||||
|
//replace the boundary of the polygon with a series of points representing triangles for rendering
|
||||||
|
polygon.points = tesselate(polygon);
|
||||||
|
|
||||||
|
curves.add(polygon);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Naively returns all of the points comprising the fractal
|
||||||
|
* @param input
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static PolygonStorage getSpaceFillingCurve(ArrayList<double[]> input)
|
||||||
|
{
|
||||||
|
// store max x and y values to create bounding box
|
||||||
|
int maxY = Integer.MIN_VALUE;
|
||||||
|
int maxX = Integer.MIN_VALUE;
|
||||||
|
int minY = Integer.MAX_VALUE;
|
||||||
|
int minX = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
// store confirmed duplicates here
|
||||||
|
HashSet<Point> duplicates = new HashSet<Point>();
|
||||||
|
|
||||||
|
// store possible singles here
|
||||||
|
HashSet<Point> singles = new HashSet<Point>();
|
||||||
|
|
||||||
|
// list to store confirmed singles and output in the correct order
|
||||||
|
ArrayList<Point> output = new ArrayList<Point>();
|
||||||
|
|
||||||
|
// sort into Hashmaps and hashsets to make contains operations possible,
|
||||||
|
// while testing for duplicates
|
||||||
|
for (double[] point : input)
|
||||||
|
{
|
||||||
|
// convert doubles to ints and record min/max values
|
||||||
|
|
||||||
|
int xCoord = (int) Math.round(point[0]);
|
||||||
|
int yCoord = (int) Math.round(point[1]);
|
||||||
|
|
||||||
|
if (xCoord > maxX)
|
||||||
|
{
|
||||||
|
maxX = xCoord;
|
||||||
|
}
|
||||||
|
if (xCoord < minX)
|
||||||
|
{
|
||||||
|
minX = xCoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yCoord > maxY)
|
||||||
|
{
|
||||||
|
maxY = yCoord;
|
||||||
|
}
|
||||||
|
if (yCoord < minY)
|
||||||
|
{
|
||||||
|
minY = yCoord;
|
||||||
|
}
|
||||||
|
output.add(new Point(xCoord, yCoord));
|
||||||
|
}
|
||||||
|
return new PolygonStorage(output, maxX, maxY, minX, minY);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes an unordered list of points comprising a fractal curve and builds a
|
||||||
|
* closed polygon around it
|
||||||
|
*
|
||||||
|
* @param input
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static PolygonStorage getBoundary(ArrayList<double[]> input)
|
||||||
|
{
|
||||||
|
// store max x and y values to create bounding box
|
||||||
|
int maxY = Integer.MIN_VALUE;
|
||||||
|
int maxX = Integer.MIN_VALUE;
|
||||||
|
int minY = Integer.MAX_VALUE;
|
||||||
|
int minX = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
// store confirmed duplicates here
|
||||||
|
HashSet<Point> duplicates = new HashSet<Point>();
|
||||||
|
|
||||||
|
// store possible singles here
|
||||||
|
HashSet<Point> singles = new HashSet<Point>();
|
||||||
|
|
||||||
|
// list to store confirmed singles and output in the correct order
|
||||||
|
ArrayList<Point> output = new ArrayList<Point>();
|
||||||
|
|
||||||
|
// sort into Hashmaps and hashsets to make contains operations possible,
|
||||||
|
// while testing for duplicates
|
||||||
|
for (double[] point : input)
|
||||||
|
{
|
||||||
|
// convert doubles to ints and record min/max values
|
||||||
|
|
||||||
|
int xCoord = (int) Math.round(point[0]);
|
||||||
|
int yCoord = (int) Math.round(point[1]);
|
||||||
|
|
||||||
|
if (xCoord > maxX)
|
||||||
|
{
|
||||||
|
maxX = xCoord;
|
||||||
|
}
|
||||||
|
if (xCoord < minX)
|
||||||
|
{
|
||||||
|
minX = xCoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yCoord > maxY)
|
||||||
|
{
|
||||||
|
maxY = yCoord;
|
||||||
|
}
|
||||||
|
if (yCoord < minY)
|
||||||
|
{
|
||||||
|
minY = yCoord;
|
||||||
|
}
|
||||||
|
singles.add(new Point(xCoord, yCoord));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// find a suitable starting point
|
||||||
|
Point startPoint = new Point(minX, minY);
|
||||||
|
Point prevPoint = (Point) startPoint.clone();
|
||||||
|
|
||||||
|
while (startPoint.y < maxY)
|
||||||
|
{
|
||||||
|
if (singles.contains(startPoint))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
startPoint.y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// record the first point so we know where to stop
|
||||||
|
final Point firstPoint = (Point) startPoint.clone();
|
||||||
|
|
||||||
|
// determine the direction to start searching from
|
||||||
|
Point direction = getVector(prevPoint, startPoint);
|
||||||
|
|
||||||
|
//output.add(startPoint);
|
||||||
|
|
||||||
|
// loop around in a clockwise circle, jumping to the next point when we
|
||||||
|
// find it and resetting the direction to start seaching from
|
||||||
|
// to the last found point. This ensures we always find the next
|
||||||
|
// *outside* point
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// get the next point
|
||||||
|
direction = rotateCounterClockwise(direction);
|
||||||
|
Point target = new Point(startPoint.x + direction.x, startPoint.y + direction.y);
|
||||||
|
|
||||||
|
// see if that point is part of our fractal curve
|
||||||
|
if (singles.contains(target))
|
||||||
|
{
|
||||||
|
if(target.equals(firstPoint))
|
||||||
|
{
|
||||||
|
output.remove(output.get(output.size()-1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// get the vector to start from for the next cycle
|
||||||
|
direction = getVector(startPoint, target);
|
||||||
|
|
||||||
|
// prune zero width spikes
|
||||||
|
if ((output.size() > 1 && output.get(output.size() - 2).equals(target)))
|
||||||
|
{
|
||||||
|
output.remove(output.size() - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
if(output.contains(target)&&!target.equals(output.get(0)))
|
||||||
|
{
|
||||||
|
int index = output.indexOf(target);
|
||||||
|
while(output.size()>index)
|
||||||
|
{
|
||||||
|
output.remove(output.size()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
output.add(target);
|
||||||
|
}
|
||||||
|
startPoint = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!(output.get(output.size() - 1).equals(firstPoint) && output.size() > 1) && output.size() < singles.size());
|
||||||
|
|
||||||
|
return new PolygonStorage(output, maxX, maxY, minX, minY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* using a point as a 2d vector, normalize it (sorta)
|
||||||
|
*
|
||||||
|
* @param origin
|
||||||
|
* @param destination
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Point getVector(Point origin, Point destination)
|
||||||
|
{
|
||||||
|
int[] normals = { origin.x - destination.x, origin.y - destination.y };
|
||||||
|
|
||||||
|
for (int i = 0; i < normals.length; i++)
|
||||||
|
{
|
||||||
|
if (normals[i] > 0)
|
||||||
|
{
|
||||||
|
normals[i] = 1;
|
||||||
|
}
|
||||||
|
else if (normals[i] == 0)
|
||||||
|
{
|
||||||
|
normals[i] = 0;
|
||||||
|
}
|
||||||
|
else if (normals[i] < 0)
|
||||||
|
{
|
||||||
|
normals[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Point(normals[0], normals[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rotate a normal around the origin
|
||||||
|
*
|
||||||
|
* @param previous
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Point rotateCounterClockwise(Point previous)
|
||||||
|
{
|
||||||
|
Point point = new Point();
|
||||||
|
|
||||||
|
point.x = (int) (previous.x * Math.cos(Math.toRadians(90)) - previous.y * Math.sin(Math.toRadians(90)));
|
||||||
|
point.y = (int) (previous.x * Math.sin(Math.toRadians(90)) + previous.y * Math.cos(Math.toRadians(90)));
|
||||||
|
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take an l-system string and convert it into a series of points on a
|
||||||
|
* cartesian grid. Designed to keep terdragons oriented the same direction
|
||||||
|
* regardless of iterations
|
||||||
|
*
|
||||||
|
* @param angle
|
||||||
|
* @param system
|
||||||
|
* @param generations
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ArrayList<double[]> convertToPoints(double angle, String system, int generations)
|
||||||
|
{
|
||||||
|
|
||||||
|
// determine the starting point and rotation to begin drawing from
|
||||||
|
int rotation = (generations % 2) == 0 ? 2 : 4;
|
||||||
|
double[] currentState = { ((generations + rotation) % 4) * 90, 0, 0 };
|
||||||
|
|
||||||
|
// the output for a totally unordered list of points defining the curve
|
||||||
|
ArrayList<double[]> output = new ArrayList<double[]>();
|
||||||
|
|
||||||
|
// the stack used to deal with branching l-systems that use [ and ]
|
||||||
|
ArrayDeque<double[]> state = new ArrayDeque<double[]>();
|
||||||
|
|
||||||
|
// perform the rules corresponding to each symbol in the l-system
|
||||||
|
for (Character ch : system.toCharArray())
|
||||||
|
{
|
||||||
|
double motion = 1;
|
||||||
|
|
||||||
|
// move forward
|
||||||
|
if (ch == 'F')
|
||||||
|
{
|
||||||
|
currentState[1] -= (Math.cos(Math.toRadians(currentState[0])) * motion);
|
||||||
|
currentState[2] -= (Math.sin(Math.toRadians(currentState[0])) * motion);
|
||||||
|
output.add(new double[] { currentState[1], currentState[2] });
|
||||||
|
|
||||||
|
}
|
||||||
|
// start branch
|
||||||
|
if (ch == '[')
|
||||||
|
{
|
||||||
|
|
||||||
|
state.push(currentState.clone());
|
||||||
|
}
|
||||||
|
// turn left
|
||||||
|
if (ch == '-')
|
||||||
|
{
|
||||||
|
currentState = new double[] { (double) ((currentState[0] - angle) % 360), currentState[1], currentState[2] };
|
||||||
|
}
|
||||||
|
// turn right
|
||||||
|
if (ch == '+')
|
||||||
|
{
|
||||||
|
currentState[0] = ((currentState[0] + angle) % 360);
|
||||||
|
|
||||||
|
}
|
||||||
|
// end branch and return to previous fork
|
||||||
|
if (ch == ']')
|
||||||
|
{
|
||||||
|
currentState = state.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* grow and l-system string based on the rules provided in the args
|
||||||
|
*
|
||||||
|
* @param start
|
||||||
|
* @param steps
|
||||||
|
* @param lSystemsRule
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String generate(String start, int steps, HashMap<String, String> lSystemsRule)
|
||||||
|
{
|
||||||
|
|
||||||
|
while (steps > 0)
|
||||||
|
{
|
||||||
|
StringBuilder output = new StringBuilder();
|
||||||
|
|
||||||
|
for (Character ch : start.toCharArray())
|
||||||
|
{
|
||||||
|
// get the rule applicable for the variable
|
||||||
|
String data = lSystemsRule.get(ch.toString());
|
||||||
|
|
||||||
|
// handle constants for rule-less symbols
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
data = ch.toString();
|
||||||
|
}
|
||||||
|
output.append(data);
|
||||||
|
}
|
||||||
|
steps--;
|
||||||
|
start = output.toString();
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
// a data container class to transmit the important information about the polygon
|
||||||
|
public static class PolygonStorage
|
||||||
|
{
|
||||||
|
public PolygonStorage(ArrayList<Point> points, int maxX, int maxY, int minX, int minY)
|
||||||
|
{
|
||||||
|
this.points = points;
|
||||||
|
this.maxX = maxX;
|
||||||
|
this.maxY = maxY;
|
||||||
|
this.minX = minX;
|
||||||
|
this.minY = minY;
|
||||||
|
}
|
||||||
|
public ArrayList<Point> points;
|
||||||
|
|
||||||
|
public int maxX;
|
||||||
|
public int maxY;
|
||||||
|
public int minX;
|
||||||
|
public int minY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static ArrayList<Point> tesselate(PolygonStorage polygon)
|
||||||
|
{
|
||||||
|
ArrayList <Point> points = new ArrayList<Point>();
|
||||||
|
|
||||||
|
ArrayList <PolygonPoint> polyPoints = new ArrayList<PolygonPoint>();
|
||||||
|
|
||||||
|
for(int i = 0; i<polygon.points.size();i++)
|
||||||
|
{
|
||||||
|
polyPoints.add(new PolygonPoint(polygon.points.get(i).x, polygon.points.get(i).y));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Polygon poly = new Polygon(polyPoints);
|
||||||
|
Poly2Tri.triangulate(poly);
|
||||||
|
|
||||||
|
ArrayList<DelaunayTriangle> tris =(ArrayList<DelaunayTriangle>) poly.getTriangles();
|
||||||
|
|
||||||
|
for(DelaunayTriangle tri : tris)
|
||||||
|
{
|
||||||
|
for(TriangulationPoint tpoint : tri.points)
|
||||||
|
{
|
||||||
|
points.add(new Point((int)tpoint.getX(),(int) tpoint.getY()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
public static ArrayList<Point> tesselate(Polygon polygon)
|
||||||
|
{
|
||||||
|
ArrayList<Point> points = new ArrayList<Point>();
|
||||||
|
|
||||||
|
Tessellator tess = new Tessellator();
|
||||||
|
double[] verticesC1 = new double[polygon.points.size()*3];
|
||||||
|
for(int i = 0; i< verticesC1.length; i+=3)
|
||||||
|
{
|
||||||
|
Point point = polygon.points.get(i/3);
|
||||||
|
verticesC1[i]= point.x;
|
||||||
|
verticesC1[i+1]= point.y;
|
||||||
|
verticesC1[i+2]= 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
tess.gluBeginPolygon();
|
||||||
|
|
||||||
|
for(int i = 0; i <polygon.points.size(); i++)
|
||||||
|
{
|
||||||
|
tess.gluTessVertex(verticesC1, i*3, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
tess.gluEndPolygon();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Prints out the result of the tessellation.
|
||||||
|
for(int i = 0; i < tess.primitives.size(); i++) {
|
||||||
|
System.out.println(tess.primitives.get(i).toString());
|
||||||
|
}
|
||||||
|
//To draw the shape it is now a simple matter to put the vertex data you passed in initially into a VBO, and the indices returned
|
||||||
|
//into an IBO (Index VBO). You have the types of the primitives and the number of indices for each one. Drawing the result should
|
||||||
|
//be a walk in the park, as long as you have read the appropriate tutorials here or elsewhere.
|
||||||
|
|
||||||
|
|
||||||
|
for(int i = 0; i < tess.primitives.size(); i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
Primitive prim = tess.primitives.get(i);
|
||||||
|
ArrayList<Integer> vIndex = prim.vertices;
|
||||||
|
|
||||||
|
if(prim.type==GL11.GL_TRIANGLE_STRIP)
|
||||||
|
{
|
||||||
|
for(Integer ii = 0; ii < vIndex.size()-1;ii++)
|
||||||
|
{
|
||||||
|
points.add(new Point((int)verticesC1[vIndex.get(ii)*3],(int) verticesC1[vIndex.get(ii)*3+1]));
|
||||||
|
points.add(new Point((int)verticesC1[vIndex.get(ii+1)*3],(int) verticesC1[vIndex.get(ii+1)*3+1]));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(prim.type==GL11.GL_TRIANGLES)
|
||||||
|
{
|
||||||
|
for(Integer ii = 0; ii < vIndex.size();ii++)
|
||||||
|
{
|
||||||
|
points.add(new Point((int)verticesC1[vIndex.get(ii)*3],(int) verticesC1[vIndex.get(ii)*3+1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
if(prim.type==GL11.GL_TRIANGLE_FAN)
|
||||||
|
{
|
||||||
|
Integer firstIndex = vIndex.get(0);
|
||||||
|
// points.add(new Point((int)verticesC1[vIndex.get(firstIndex)],(int) verticesC1[vIndex.get(firstIndex)+1]));
|
||||||
|
|
||||||
|
Integer[] vertexList = new Integer[vIndex.size()*3];
|
||||||
|
for(Integer ii = 0; ii < vIndex.size()-2;ii++)
|
||||||
|
{
|
||||||
|
vertexList[ii*3] = vIndex.get(0);
|
||||||
|
vertexList[ii*3+1] = vIndex.get(ii+1);
|
||||||
|
vertexList[ii*3+2] = vIndex.get(ii+2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Integer vertex : vertexList)
|
||||||
|
{
|
||||||
|
if(vertex!=null)
|
||||||
|
{
|
||||||
|
points.add(new Point((int)(verticesC1[vertex*3]),(int)(verticesC1[vertex*3+1])));
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println(vertexList);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//points.add(new Point((int)verticesC1[vIndex.get(firstIndex)],(int) verticesC1[vIndex.get(firstIndex)+1]));
|
||||||
|
// points.add(new Point((int)verticesC1[vIndex.get(ii)*3],(int) verticesC1[vIndex.get(ii)+1]));
|
||||||
|
// points.add(new Point((int)verticesC1[vIndex.get(ii+1)*3],(int) verticesC1[vIndex.get(ii+1)*3+1]));
|
||||||
|
|
||||||
|
// points.add(new Point((int)verticesC1[index],(int)verticesC1[index+1]));
|
||||||
|
// System.out.println(verticesC1[index]+","+verticesC1[index+1]+","+verticesC1[index+2]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
//System.out.println(tess.primitives.get(i).toString());
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
|
||||||
|
}
|
||||||
|
**/
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import StevenDimDoors.mod_pocketDim.core.DimLink;
|
|||||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||||
import StevenDimDoors.mod_pocketDim.ticking.MobMonolith;
|
import StevenDimDoors.mod_pocketDim.ticking.MobMonolith;
|
||||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityDimDoor;
|
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityDimDoor;
|
||||||
|
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityRift;
|
||||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityTransTrapdoor;
|
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityTransTrapdoor;
|
||||||
import StevenDimDoors.mod_pocketDim.watcher.ClientLinkData;
|
import StevenDimDoors.mod_pocketDim.watcher.ClientLinkData;
|
||||||
import cpw.mods.fml.client.registry.ClientRegistry;
|
import cpw.mods.fml.client.registry.ClientRegistry;
|
||||||
@@ -23,7 +24,7 @@ public class ClientProxy extends CommonProxy
|
|||||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityDimDoor.class, new RenderDimDoor());
|
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityDimDoor.class, new RenderDimDoor());
|
||||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityTransTrapdoor.class, new RenderTransTrapdoor());
|
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityTransTrapdoor.class, new RenderTransTrapdoor());
|
||||||
//This code activates the new rift rendering, as well as a bit of code in TileEntityRift
|
//This code activates the new rift rendering, as well as a bit of code in TileEntityRift
|
||||||
//ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRift.class, new RenderRift());
|
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRift.class, new RenderRift());
|
||||||
|
|
||||||
//MinecraftForgeClient.preloadTexture(RIFT2_PNG);
|
//MinecraftForgeClient.preloadTexture(RIFT2_PNG);
|
||||||
RenderingRegistry.registerEntityRenderingHandler(MobMonolith.class, new RenderMobObelisk(.5F));
|
RenderingRegistry.registerEntityRenderingHandler(MobMonolith.class, new RenderMobObelisk(.5F));
|
||||||
|
|||||||
168
src/main/java/StevenDimDoors/mod_pocketDimClient/RenderRift.java
Normal file
168
src/main/java/StevenDimDoors/mod_pocketDimClient/RenderRift.java
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDimClient;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL11.*;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityRift;
|
||||||
|
import StevenDimDoors.mod_pocketDim.util.l_systems.LSystem;
|
||||||
|
import StevenDimDoors.mod_pocketDim.util.l_systems.LSystem.PolygonStorage;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class RenderRift extends TileEntitySpecialRenderer
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderTileEntityAt(TileEntity te, double xWorld, double yWorld, double zWorld, float f)
|
||||||
|
{
|
||||||
|
// prepare fb for drawing
|
||||||
|
GL11.glPushMatrix();
|
||||||
|
|
||||||
|
// make the rift render on both sides, disable texture mapping and
|
||||||
|
// lighting
|
||||||
|
GL11.glDisable(GL11.GL_CULL_FACE);
|
||||||
|
GL11.glDisable(GL_TEXTURE_2D);
|
||||||
|
GL11.glDisable(GL_LIGHTING);
|
||||||
|
GL11.glEnable(GL_BLEND);
|
||||||
|
/**
|
||||||
|
* GL11.glLogicOp(GL11.GL_INVERT);
|
||||||
|
* GL11.glEnable(GL11.GL_COLOR_LOGIC_OP);
|
||||||
|
*/
|
||||||
|
TileEntityRift rift = (TileEntityRift) te;
|
||||||
|
// draws the verticies corresponding to the passed it
|
||||||
|
this.drawCrack(rift.riftRotation, rift.getCurve(), rift.growth/15, xWorld, yWorld, zWorld);
|
||||||
|
|
||||||
|
GL11.glDisable(GL_BLEND);
|
||||||
|
// reenable all the stuff we disabled
|
||||||
|
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||||
|
GL11.glEnable(GL11.GL_LIGHTING);
|
||||||
|
GL11.glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
GL11.glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* method that draws the fractal and applies animations/effects
|
||||||
|
*
|
||||||
|
* f
|
||||||
|
*
|
||||||
|
* @param riftRotation
|
||||||
|
* @param poly
|
||||||
|
* @param size
|
||||||
|
* @param xWorld
|
||||||
|
* @param yWorld
|
||||||
|
* @param zWorld
|
||||||
|
*/
|
||||||
|
public void drawCrack(int riftRotation, PolygonStorage poly, double size, double xWorld, double yWorld, double zWorld)
|
||||||
|
{
|
||||||
|
// calculate the proper size for the rift render
|
||||||
|
double scale = size / (poly.maxX - poly.minX);
|
||||||
|
|
||||||
|
// calculate the midpoint of the fractal bounding box
|
||||||
|
double offsetX = ((poly.maxX + poly.minX)) / 2;
|
||||||
|
double offsetY = ((poly.maxY + poly.minY)) / 2;
|
||||||
|
double offsetZ = 0;
|
||||||
|
|
||||||
|
// changes how far the triangles move
|
||||||
|
float motionMagnitude = 3.0F;
|
||||||
|
|
||||||
|
// changes how quickly the triangles move
|
||||||
|
float motionSpeed = 2000.0F;
|
||||||
|
|
||||||
|
// number of individual jitter waveforms to generate
|
||||||
|
// changes how "together" the overall motions are
|
||||||
|
int jCount = 5;
|
||||||
|
|
||||||
|
// Calculate jitter like for monoliths
|
||||||
|
float time = (float) (((Minecraft.getSystemTime() + 0xF1234568 * this.hashCode()) % 2000000) / motionSpeed);
|
||||||
|
double[] jitters = new double[jCount];
|
||||||
|
|
||||||
|
// generate a series of waveforms
|
||||||
|
for (int i = 0; i < jCount - 1; i += 1)
|
||||||
|
{
|
||||||
|
jitters[i] = Math.sin((1F + i / 10F) * time) * Math.cos(1F - (i / 10F) * time) / motionMagnitude;
|
||||||
|
jitters[i + 1] = Math.cos((1F + i / 10F) * time) * Math.sin(1F - (i / 10F) * time) / motionMagnitude;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// determines which jitter waveform we select. Modulo so the same point
|
||||||
|
// gets the same jitter waveform over multiple frames
|
||||||
|
int jIndex = 0;
|
||||||
|
// set the color for the render
|
||||||
|
GL11.glColor4f(.1F, .1F, .1F, 1F);
|
||||||
|
|
||||||
|
// set the blending mode
|
||||||
|
GL11.glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_ONE_MINUS_SRC_COLOR, GL_ONE);
|
||||||
|
GL11.glBegin(GL11.GL_TRIANGLES);
|
||||||
|
for (Point p : poly.points)
|
||||||
|
{
|
||||||
|
jIndex = Math.abs(((p.x + p.y) * (p.x + p.y + 1) / 2) + p.y);
|
||||||
|
// jIndex++;
|
||||||
|
// calculate the rotation for the fractal, apply offset, and apply
|
||||||
|
// jitter
|
||||||
|
double x = (((p.x + jitters[(jIndex + 1) % jCount]) - offsetX) * Math.cos(Math.toRadians(riftRotation)) - (jitters[(jIndex + 2) % jCount])
|
||||||
|
* Math.sin(Math.toRadians(riftRotation)));
|
||||||
|
double y = p.y + (jitters[jIndex % jCount]) - offsetY;
|
||||||
|
double z = (((p.x + jitters[(jIndex + 2) % jCount]) - offsetX) * Math.sin(Math.toRadians(riftRotation)) + (jitters[(jIndex + 2) % jCount])
|
||||||
|
* Math.cos(Math.toRadians(riftRotation)));
|
||||||
|
|
||||||
|
// apply scaling
|
||||||
|
x *= scale;
|
||||||
|
y *= scale;
|
||||||
|
z *= scale;
|
||||||
|
|
||||||
|
// apply transform to center the offset origin into the middle of a
|
||||||
|
// block
|
||||||
|
x += .5;
|
||||||
|
y += .5;
|
||||||
|
z += .5;
|
||||||
|
|
||||||
|
// draw the vertex and apply the world (screenspace) relative
|
||||||
|
// coordinates
|
||||||
|
GL11.glVertex3d(xWorld + x, yWorld + y, zWorld + z);
|
||||||
|
}
|
||||||
|
GL11.glEnd();
|
||||||
|
|
||||||
|
GL11.glColor4f(.3F, .3F, .3F, .2F);
|
||||||
|
|
||||||
|
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||||
|
|
||||||
|
// draw the next set of triangles to form a background and change their
|
||||||
|
// color slightly over time
|
||||||
|
GL11.glBegin(GL11.GL_TRIANGLES);
|
||||||
|
for (Point p : poly.points)
|
||||||
|
{
|
||||||
|
jIndex++;
|
||||||
|
|
||||||
|
double x = (((p.x) - offsetX) * Math.cos(Math.toRadians(riftRotation)) - 0 * Math.sin(Math.toRadians(riftRotation)));
|
||||||
|
double y = p.y - offsetY;
|
||||||
|
double z = (((p.x) - offsetX) * Math.sin(Math.toRadians(riftRotation)) + 0 * Math.cos(Math.toRadians(riftRotation)));
|
||||||
|
|
||||||
|
x *= scale;
|
||||||
|
y *= scale;
|
||||||
|
z *= scale;
|
||||||
|
|
||||||
|
x += .5;
|
||||||
|
y += .5;
|
||||||
|
z += .5;
|
||||||
|
|
||||||
|
if (jIndex % 3 == 0)
|
||||||
|
{
|
||||||
|
// GL11.glColor4d(1-jitters[(jIndex + 5) % jCount] / 11,1-
|
||||||
|
// jitters[(jIndex + 4) % jCount] / 8, 1-jitters[(jIndex+3) %
|
||||||
|
// jCount] / 8, 1);
|
||||||
|
}
|
||||||
|
GL11.glVertex3d(xWorld + x, yWorld + y, zWorld + z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop drawing triangles
|
||||||
|
GL11.glEnd();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
124
src/main/java/org/poly2tri/Poly2Tri.java
Normal file
124
src/main/java/org/poly2tri/Poly2Tri.java
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri;
|
||||||
|
|
||||||
|
import org.poly2tri.geometry.polygon.Polygon;
|
||||||
|
import org.poly2tri.geometry.polygon.PolygonSet;
|
||||||
|
import org.poly2tri.triangulation.Triangulatable;
|
||||||
|
import org.poly2tri.triangulation.TriangulationAlgorithm;
|
||||||
|
import org.poly2tri.triangulation.TriangulationContext;
|
||||||
|
import org.poly2tri.triangulation.TriangulationMode;
|
||||||
|
import org.poly2tri.triangulation.TriangulationProcess;
|
||||||
|
import org.poly2tri.triangulation.delaunay.sweep.DTSweep;
|
||||||
|
import org.poly2tri.triangulation.delaunay.sweep.DTSweepContext;
|
||||||
|
import org.poly2tri.triangulation.sets.ConstrainedPointSet;
|
||||||
|
import org.poly2tri.triangulation.sets.PointSet;
|
||||||
|
import org.poly2tri.triangulation.util.PolygonGenerator;
|
||||||
|
|
||||||
|
public class Poly2Tri
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final TriangulationAlgorithm _defaultAlgorithm = TriangulationAlgorithm.DTSweep;
|
||||||
|
|
||||||
|
public static void triangulate( PolygonSet ps )
|
||||||
|
{
|
||||||
|
TriangulationContext<?> tcx = createContext( _defaultAlgorithm );
|
||||||
|
for( Polygon p : ps.getPolygons() )
|
||||||
|
{
|
||||||
|
tcx.prepareTriangulation( p );
|
||||||
|
triangulate( tcx );
|
||||||
|
tcx.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void triangulate( Polygon p )
|
||||||
|
{
|
||||||
|
triangulate( _defaultAlgorithm, p );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void triangulate( ConstrainedPointSet cps )
|
||||||
|
{
|
||||||
|
triangulate( _defaultAlgorithm, cps );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void triangulate( PointSet ps )
|
||||||
|
{
|
||||||
|
triangulate( _defaultAlgorithm, ps );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TriangulationContext<?> createContext( TriangulationAlgorithm algorithm )
|
||||||
|
{
|
||||||
|
switch( algorithm )
|
||||||
|
{
|
||||||
|
case DTSweep:
|
||||||
|
default:
|
||||||
|
return new DTSweepContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void triangulate( TriangulationAlgorithm algorithm,
|
||||||
|
Triangulatable t )
|
||||||
|
{
|
||||||
|
TriangulationContext<?> tcx;
|
||||||
|
|
||||||
|
// long time = System.nanoTime();
|
||||||
|
tcx = createContext( algorithm );
|
||||||
|
tcx.prepareTriangulation( t );
|
||||||
|
triangulate( tcx );
|
||||||
|
// logger.info( "Triangulation of {} points [{}ms]", tcx.getPoints().size(), ( System.nanoTime() - time ) / 1e6 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void triangulate( TriangulationContext<?> tcx )
|
||||||
|
{
|
||||||
|
switch( tcx.algorithm() )
|
||||||
|
{
|
||||||
|
case DTSweep:
|
||||||
|
default:
|
||||||
|
DTSweep.triangulate( (DTSweepContext)tcx );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will do a warmup run to let the JVM optimize the triangulation code
|
||||||
|
*/
|
||||||
|
public static void warmup()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* After a method is run 10000 times, the Hotspot compiler will compile
|
||||||
|
* it into native code. Periodically, the Hotspot compiler may recompile
|
||||||
|
* the method. After an unspecified amount of time, then the compilation
|
||||||
|
* system should become quiet.
|
||||||
|
*/
|
||||||
|
Polygon poly = PolygonGenerator.RandomCircleSweep2( 50, 50000 );
|
||||||
|
TriangulationProcess process = new TriangulationProcess();
|
||||||
|
process.triangulate( poly );
|
||||||
|
}
|
||||||
|
}
|
||||||
269
src/main/java/org/poly2tri/geometry/polygon/Polygon.java
Normal file
269
src/main/java/org/poly2tri/geometry/polygon/Polygon.java
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
package org.poly2tri.geometry.polygon;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.poly2tri.triangulation.Triangulatable;
|
||||||
|
import org.poly2tri.triangulation.TriangulationContext;
|
||||||
|
import org.poly2tri.triangulation.TriangulationMode;
|
||||||
|
import org.poly2tri.triangulation.TriangulationPoint;
|
||||||
|
import org.poly2tri.triangulation.delaunay.DelaunayTriangle;
|
||||||
|
|
||||||
|
public class Polygon implements Triangulatable
|
||||||
|
{
|
||||||
|
|
||||||
|
protected ArrayList<TriangulationPoint> _points = new ArrayList<TriangulationPoint>();
|
||||||
|
protected ArrayList<TriangulationPoint> _steinerPoints;
|
||||||
|
protected ArrayList<Polygon> _holes;
|
||||||
|
|
||||||
|
protected List<DelaunayTriangle> m_triangles;
|
||||||
|
|
||||||
|
protected PolygonPoint _last;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To create a polygon we need atleast 3 separate points
|
||||||
|
*
|
||||||
|
* @param p1
|
||||||
|
* @param p2
|
||||||
|
* @param p3
|
||||||
|
*/
|
||||||
|
public Polygon( PolygonPoint p1, PolygonPoint p2, PolygonPoint p3 )
|
||||||
|
{
|
||||||
|
p1._next = p2;
|
||||||
|
p2._next = p3;
|
||||||
|
p3._next = p1;
|
||||||
|
p1._previous = p3;
|
||||||
|
p2._previous = p1;
|
||||||
|
p3._previous = p2;
|
||||||
|
_points.add( p1 );
|
||||||
|
_points.add( p2 );
|
||||||
|
_points.add( p3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requires atleast 3 points
|
||||||
|
* @param points - ordered list of points forming the polygon.
|
||||||
|
* No duplicates are allowed
|
||||||
|
*/
|
||||||
|
public Polygon( List<PolygonPoint> points )
|
||||||
|
{
|
||||||
|
// Lets do one sanity check that first and last point hasn't got same position
|
||||||
|
// Its something that often happen when importing polygon data from other formats
|
||||||
|
if( points.get(0).equals( points.get(points.size()-1) ) )
|
||||||
|
{
|
||||||
|
points.remove( points.size()-1 );
|
||||||
|
}
|
||||||
|
_points.addAll( points );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requires atleast 3 points
|
||||||
|
*
|
||||||
|
* @param points
|
||||||
|
*/
|
||||||
|
public Polygon( PolygonPoint[] points )
|
||||||
|
{
|
||||||
|
this( Arrays.asList( points ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriangulationMode getTriangulationMode()
|
||||||
|
{
|
||||||
|
return TriangulationMode.POLYGON;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int pointCount()
|
||||||
|
{
|
||||||
|
int count = _points.size();
|
||||||
|
if( _steinerPoints != null )
|
||||||
|
{
|
||||||
|
count += _steinerPoints.size();
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSteinerPoint( TriangulationPoint point )
|
||||||
|
{
|
||||||
|
if( _steinerPoints == null )
|
||||||
|
{
|
||||||
|
_steinerPoints = new ArrayList<TriangulationPoint>();
|
||||||
|
}
|
||||||
|
_steinerPoints.add( point );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSteinerPoints( List<TriangulationPoint> points )
|
||||||
|
{
|
||||||
|
if( _steinerPoints == null )
|
||||||
|
{
|
||||||
|
_steinerPoints = new ArrayList<TriangulationPoint>();
|
||||||
|
}
|
||||||
|
_steinerPoints.addAll( points );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearSteinerPoints()
|
||||||
|
{
|
||||||
|
if( _steinerPoints != null )
|
||||||
|
{
|
||||||
|
_steinerPoints.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assumes: that given polygon is fully inside the current polygon
|
||||||
|
* @param poly - a subtraction polygon
|
||||||
|
*/
|
||||||
|
public void addHole( Polygon poly )
|
||||||
|
{
|
||||||
|
if( _holes == null )
|
||||||
|
{
|
||||||
|
_holes = new ArrayList<Polygon>();
|
||||||
|
}
|
||||||
|
_holes.add( poly );
|
||||||
|
// XXX: tests could be made here to be sure it is fully inside
|
||||||
|
// addSubtraction( poly.getPoints() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will insert a point in the polygon after given point
|
||||||
|
*
|
||||||
|
* @param a
|
||||||
|
* @param b
|
||||||
|
* @param p
|
||||||
|
*/
|
||||||
|
public void insertPointAfter( PolygonPoint a, PolygonPoint newPoint )
|
||||||
|
{
|
||||||
|
// Validate that
|
||||||
|
int index = _points.indexOf( a );
|
||||||
|
if( index != -1 )
|
||||||
|
{
|
||||||
|
newPoint.setNext( a.getNext() );
|
||||||
|
newPoint.setPrevious( a );
|
||||||
|
a.getNext().setPrevious( newPoint );
|
||||||
|
a.setNext( newPoint );
|
||||||
|
_points.add( index+1, newPoint );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RuntimeException( "Tried to insert a point into a Polygon after a point not belonging to the Polygon" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPoints( List<PolygonPoint> list )
|
||||||
|
{
|
||||||
|
PolygonPoint first;
|
||||||
|
for( PolygonPoint p : list )
|
||||||
|
{
|
||||||
|
p.setPrevious( _last );
|
||||||
|
if( _last != null )
|
||||||
|
{
|
||||||
|
p.setNext( _last.getNext() );
|
||||||
|
_last.setNext( p );
|
||||||
|
}
|
||||||
|
_last = p;
|
||||||
|
_points.add( p );
|
||||||
|
}
|
||||||
|
first = (PolygonPoint)_points.get(0);
|
||||||
|
_last.setNext( first );
|
||||||
|
first.setPrevious( _last );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will add a point after the last point added
|
||||||
|
*
|
||||||
|
* @param p
|
||||||
|
*/
|
||||||
|
public void addPoint(PolygonPoint p )
|
||||||
|
{
|
||||||
|
p.setPrevious( _last );
|
||||||
|
p.setNext( _last.getNext() );
|
||||||
|
_last.setNext( p );
|
||||||
|
_points.add( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePoint( PolygonPoint p )
|
||||||
|
{
|
||||||
|
PolygonPoint next, prev;
|
||||||
|
|
||||||
|
next = p.getNext();
|
||||||
|
prev = p.getPrevious();
|
||||||
|
prev.setNext( next );
|
||||||
|
next.setPrevious( prev );
|
||||||
|
_points.remove( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
public PolygonPoint getPoint()
|
||||||
|
{
|
||||||
|
return _last;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TriangulationPoint> getPoints()
|
||||||
|
{
|
||||||
|
return _points;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DelaunayTriangle> getTriangles()
|
||||||
|
{
|
||||||
|
return m_triangles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTriangle( DelaunayTriangle t )
|
||||||
|
{
|
||||||
|
m_triangles.add( t );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTriangles( List<DelaunayTriangle> list )
|
||||||
|
{
|
||||||
|
m_triangles.addAll( list );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearTriangulation()
|
||||||
|
{
|
||||||
|
if( m_triangles != null )
|
||||||
|
{
|
||||||
|
m_triangles.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates constraints and populates the context with points
|
||||||
|
*/
|
||||||
|
public void prepareTriangulation( TriangulationContext<?> tcx )
|
||||||
|
{
|
||||||
|
if( m_triangles == null )
|
||||||
|
{
|
||||||
|
m_triangles = new ArrayList<DelaunayTriangle>( _points.size() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_triangles.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outer constraints
|
||||||
|
for( int i = 0; i < _points.size()-1 ; i++ )
|
||||||
|
{
|
||||||
|
tcx.newConstraint( _points.get( i ), _points.get( i+1 ) );
|
||||||
|
}
|
||||||
|
tcx.newConstraint( _points.get( 0 ), _points.get( _points.size()-1 ) );
|
||||||
|
tcx.addPoints( _points );
|
||||||
|
|
||||||
|
// Hole constraints
|
||||||
|
if( _holes != null )
|
||||||
|
{
|
||||||
|
for( Polygon p : _holes )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < p._points.size()-1 ; i++ )
|
||||||
|
{
|
||||||
|
tcx.newConstraint( p._points.get( i ), p._points.get( i+1 ) );
|
||||||
|
}
|
||||||
|
tcx.newConstraint( p._points.get( 0 ), p._points.get( p._points.size()-1 ) );
|
||||||
|
tcx.addPoints( p._points );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _steinerPoints != null )
|
||||||
|
{
|
||||||
|
tcx.addPoints( _steinerPoints );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package org.poly2tri.geometry.polygon;
|
||||||
|
|
||||||
|
import org.poly2tri.triangulation.point.TPoint;
|
||||||
|
|
||||||
|
public class PolygonPoint extends TPoint
|
||||||
|
{
|
||||||
|
protected PolygonPoint _next;
|
||||||
|
protected PolygonPoint _previous;
|
||||||
|
|
||||||
|
public PolygonPoint( double x, double y )
|
||||||
|
{
|
||||||
|
super( x, y );
|
||||||
|
}
|
||||||
|
|
||||||
|
public PolygonPoint( double x, double y, double z )
|
||||||
|
{
|
||||||
|
super( x, y, z );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrevious( PolygonPoint p )
|
||||||
|
{
|
||||||
|
_previous = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNext( PolygonPoint p )
|
||||||
|
{
|
||||||
|
_next = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PolygonPoint getNext()
|
||||||
|
{
|
||||||
|
return _next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PolygonPoint getPrevious()
|
||||||
|
{
|
||||||
|
return _previous;
|
||||||
|
}
|
||||||
|
}
|
||||||
58
src/main/java/org/poly2tri/geometry/polygon/PolygonSet.java
Normal file
58
src/main/java/org/poly2tri/geometry/polygon/PolygonSet.java
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.geometry.polygon;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PolygonSet
|
||||||
|
{
|
||||||
|
protected ArrayList<Polygon> _polygons = new ArrayList<Polygon>();
|
||||||
|
|
||||||
|
public PolygonSet()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PolygonSet( Polygon poly )
|
||||||
|
{
|
||||||
|
_polygons.add( poly );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add( Polygon p )
|
||||||
|
{
|
||||||
|
_polygons.add( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Polygon> getPolygons()
|
||||||
|
{
|
||||||
|
return _polygons;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/main/java/org/poly2tri/geometry/polygon/PolygonUtil.java
Normal file
15
src/main/java/org/poly2tri/geometry/polygon/PolygonUtil.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package org.poly2tri.geometry.polygon;
|
||||||
|
|
||||||
|
public class PolygonUtil
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
* @param polygon
|
||||||
|
*/
|
||||||
|
public static void validate( Polygon polygon )
|
||||||
|
{
|
||||||
|
// TODO: implement
|
||||||
|
// 1. Check for duplicate points
|
||||||
|
// 2. Check for intersecting sides
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/main/java/org/poly2tri/geometry/primitives/Edge.java
Normal file
17
src/main/java/org/poly2tri/geometry/primitives/Edge.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package org.poly2tri.geometry.primitives;
|
||||||
|
|
||||||
|
public abstract class Edge<A extends Point>
|
||||||
|
{
|
||||||
|
protected A p;
|
||||||
|
protected A q;
|
||||||
|
|
||||||
|
public A getP()
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public A getQ()
|
||||||
|
{
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/main/java/org/poly2tri/geometry/primitives/Point.java
Normal file
31
src/main/java/org/poly2tri/geometry/primitives/Point.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package org.poly2tri.geometry.primitives;
|
||||||
|
|
||||||
|
public abstract class Point
|
||||||
|
{
|
||||||
|
public abstract double getX();
|
||||||
|
public abstract double getY();
|
||||||
|
public abstract double getZ();
|
||||||
|
|
||||||
|
public abstract float getXf();
|
||||||
|
public abstract float getYf();
|
||||||
|
public abstract float getZf();
|
||||||
|
|
||||||
|
public abstract void set( double x, double y, double z );
|
||||||
|
|
||||||
|
protected static int calculateHashCode( double x, double y, double z)
|
||||||
|
{
|
||||||
|
int result = 17;
|
||||||
|
|
||||||
|
final long a = Double.doubleToLongBits(x);
|
||||||
|
result += 31 * result + (int) (a ^ (a >>> 32));
|
||||||
|
|
||||||
|
final long b = Double.doubleToLongBits(y);
|
||||||
|
result += 31 * result + (int) (b ^ (b >>> 32));
|
||||||
|
|
||||||
|
final long c = Double.doubleToLongBits(z);
|
||||||
|
result += 31 * result + (int) (c ^ (c >>> 32));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package org.poly2tri.transform.coordinate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A transform that aligns given source normal with the XY plane normal [0,0,1]
|
||||||
|
*
|
||||||
|
* @author thahlen@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class AnyToXYTransform extends Matrix3Transform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Assumes source normal is normalized
|
||||||
|
*/
|
||||||
|
public AnyToXYTransform( double nx, double ny, double nz )
|
||||||
|
{
|
||||||
|
setSourceNormal( nx, ny, nz );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assumes source normal is normalized
|
||||||
|
*
|
||||||
|
* @param nx
|
||||||
|
* @param ny
|
||||||
|
* @param nz
|
||||||
|
*/
|
||||||
|
public void setSourceNormal( double nx, double ny, double nz )
|
||||||
|
{
|
||||||
|
double h,f,c,vx,vy,hvx;
|
||||||
|
|
||||||
|
vx = -ny;
|
||||||
|
vy = nx;
|
||||||
|
c = nz;
|
||||||
|
|
||||||
|
h = (1-c)/(1-c*c);
|
||||||
|
hvx = h*vx;
|
||||||
|
f = (c < 0) ? -c : c;
|
||||||
|
|
||||||
|
if( f < 1.0 - 1.0E-4 )
|
||||||
|
{
|
||||||
|
m00=c + hvx*vx;
|
||||||
|
m01=hvx*vy;
|
||||||
|
m02=-vy;
|
||||||
|
m10=hvx*vy;
|
||||||
|
m11=c + h*vy*vy;
|
||||||
|
m12=vx;
|
||||||
|
m20=vy;
|
||||||
|
m21=-vx;
|
||||||
|
m22=c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if "from" and "to" vectors are nearly parallel
|
||||||
|
m00=1;
|
||||||
|
m01=0;
|
||||||
|
m02=0;
|
||||||
|
m10=0;
|
||||||
|
m11=1;
|
||||||
|
m12=0;
|
||||||
|
m20=0;
|
||||||
|
m21=0;
|
||||||
|
if( c > 0 )
|
||||||
|
{
|
||||||
|
m22=1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m22=-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.poly2tri.transform.coordinate;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.poly2tri.geometry.primitives.Point;
|
||||||
|
|
||||||
|
public abstract interface CoordinateTransform
|
||||||
|
{
|
||||||
|
public abstract void transform( Point p, Point store );
|
||||||
|
public abstract void transform( Point p );
|
||||||
|
public abstract void transform( List<? extends Point> list );
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package org.poly2tri.transform.coordinate;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.poly2tri.geometry.primitives.Point;
|
||||||
|
|
||||||
|
public abstract class Matrix3Transform implements CoordinateTransform
|
||||||
|
{
|
||||||
|
protected double m00,m01,m02,m10,m11,m12,m20,m21,m22;
|
||||||
|
|
||||||
|
public void transform( Point p, Point store )
|
||||||
|
{
|
||||||
|
final double px = p.getX();
|
||||||
|
final double py = p.getY();
|
||||||
|
final double pz = p.getZ();
|
||||||
|
store.set(m00 * px + m01 * py + m02 * pz,
|
||||||
|
m10 * px + m11 * py + m12 * pz,
|
||||||
|
m20 * px + m21 * py + m22 * pz );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void transform( Point p )
|
||||||
|
{
|
||||||
|
final double px = p.getX();
|
||||||
|
final double py = p.getY();
|
||||||
|
final double pz = p.getZ();
|
||||||
|
p.set(m00 * px + m01 * py + m02 * pz,
|
||||||
|
m10 * px + m11 * py + m12 * pz,
|
||||||
|
m20 * px + m21 * py + m22 * pz );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void transform( List<? extends Point> list )
|
||||||
|
{
|
||||||
|
for( Point p : list )
|
||||||
|
{
|
||||||
|
transform( p );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package org.poly2tri.transform.coordinate;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.poly2tri.geometry.primitives.Point;
|
||||||
|
|
||||||
|
public class NoTransform implements CoordinateTransform
|
||||||
|
{
|
||||||
|
public void transform( Point p, Point store )
|
||||||
|
{
|
||||||
|
store.set( p.getX(), p.getY(), p.getZ() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void transform( Point p )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void transform( List<? extends Point> list )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package org.poly2tri.transform.coordinate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A transform that aligns the XY plane normal [0,0,1] with any given target normal
|
||||||
|
*
|
||||||
|
* http://www.cs.brown.edu/~jfh/papers/Moller-EBA-1999/paper.pdf
|
||||||
|
*
|
||||||
|
* @author thahlen@gmail.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class XYToAnyTransform extends Matrix3Transform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Assumes target normal is normalized
|
||||||
|
*/
|
||||||
|
public XYToAnyTransform( double nx, double ny, double nz )
|
||||||
|
{
|
||||||
|
setTargetNormal( nx, ny, nz );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assumes target normal is normalized
|
||||||
|
*
|
||||||
|
* @param nx
|
||||||
|
* @param ny
|
||||||
|
* @param nz
|
||||||
|
*/
|
||||||
|
public void setTargetNormal( double nx, double ny, double nz )
|
||||||
|
{
|
||||||
|
double h,f,c,vx,vy,hvx;
|
||||||
|
|
||||||
|
vx = ny;
|
||||||
|
vy = -nx;
|
||||||
|
c = nz;
|
||||||
|
|
||||||
|
h = (1-c)/(1-c*c);
|
||||||
|
hvx = h*vx;
|
||||||
|
f = (c < 0) ? -c : c;
|
||||||
|
|
||||||
|
if( f < 1.0 - 1.0E-4 )
|
||||||
|
{
|
||||||
|
m00=c + hvx*vx;
|
||||||
|
m01=hvx*vy;
|
||||||
|
m02=-vy;
|
||||||
|
m10=hvx*vy;
|
||||||
|
m11=c + h*vy*vy;
|
||||||
|
m12=vx;
|
||||||
|
m20=vy;
|
||||||
|
m21=-vx;
|
||||||
|
m22=c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if "from" and "to" vectors are nearly parallel
|
||||||
|
m00=1;
|
||||||
|
m01=0;
|
||||||
|
m02=0;
|
||||||
|
m10=0;
|
||||||
|
m11=1;
|
||||||
|
m12=0;
|
||||||
|
m20=0;
|
||||||
|
m21=0;
|
||||||
|
if( c > 0 )
|
||||||
|
{
|
||||||
|
m22=1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m22=-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/main/java/org/poly2tri/triangulation/Triangulatable.java
Normal file
22
src/main/java/org/poly2tri/triangulation/Triangulatable.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package org.poly2tri.triangulation;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.poly2tri.triangulation.delaunay.DelaunayTriangle;
|
||||||
|
|
||||||
|
public interface Triangulatable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Preparations needed before triangulation start should be handled here
|
||||||
|
* @param tcx
|
||||||
|
*/
|
||||||
|
public void prepareTriangulation( TriangulationContext<?> tcx );
|
||||||
|
|
||||||
|
public List<DelaunayTriangle> getTriangles();
|
||||||
|
public List<TriangulationPoint> getPoints();
|
||||||
|
public void addTriangle( DelaunayTriangle t );
|
||||||
|
public void addTriangles( List<DelaunayTriangle> list );
|
||||||
|
public void clearTriangulation();
|
||||||
|
|
||||||
|
public TriangulationMode getTriangulationMode();
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation;
|
||||||
|
|
||||||
|
public enum TriangulationAlgorithm
|
||||||
|
{
|
||||||
|
DTSweep
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forces a triangle edge between two points p and q
|
||||||
|
* when triangulating. For example used to enforce
|
||||||
|
* Polygon Edges during a polygon triangulation.
|
||||||
|
*
|
||||||
|
* @author Thomas <20>hl<68>n, thahlen@gmail.com
|
||||||
|
*/
|
||||||
|
public class TriangulationConstraint
|
||||||
|
{
|
||||||
|
protected TriangulationPoint p;
|
||||||
|
protected TriangulationPoint q;
|
||||||
|
|
||||||
|
public TriangulationPoint getP()
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriangulationPoint getQ()
|
||||||
|
{
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.poly2tri.triangulation.delaunay.DelaunayTriangle;
|
||||||
|
|
||||||
|
public abstract class TriangulationContext<A extends TriangulationDebugContext>
|
||||||
|
{
|
||||||
|
protected A _debug;
|
||||||
|
protected boolean _debugEnabled = false;
|
||||||
|
|
||||||
|
protected ArrayList<DelaunayTriangle> _triList = new ArrayList<DelaunayTriangle>();
|
||||||
|
|
||||||
|
protected ArrayList<TriangulationPoint> _points = new ArrayList<TriangulationPoint>(200);
|
||||||
|
protected TriangulationMode _triangulationMode;
|
||||||
|
protected Triangulatable _triUnit;
|
||||||
|
|
||||||
|
private boolean _terminated = false;
|
||||||
|
private boolean _waitUntilNotified;
|
||||||
|
|
||||||
|
private int _stepTime = -1;
|
||||||
|
private int _stepCount = 0;
|
||||||
|
public int getStepCount() { return _stepCount; }
|
||||||
|
|
||||||
|
public void done()
|
||||||
|
{
|
||||||
|
_stepCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract TriangulationAlgorithm algorithm();
|
||||||
|
|
||||||
|
public void prepareTriangulation( Triangulatable t )
|
||||||
|
{
|
||||||
|
_triUnit = t;
|
||||||
|
_triangulationMode = t.getTriangulationMode();
|
||||||
|
t.prepareTriangulation( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract TriangulationConstraint newConstraint( TriangulationPoint a, TriangulationPoint b );
|
||||||
|
|
||||||
|
public void addToList( DelaunayTriangle triangle )
|
||||||
|
{
|
||||||
|
_triList.add( triangle );
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DelaunayTriangle> getTriangles()
|
||||||
|
{
|
||||||
|
return _triList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Triangulatable getTriangulatable()
|
||||||
|
{
|
||||||
|
return _triUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TriangulationPoint> getPoints()
|
||||||
|
{
|
||||||
|
return _points;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void update(String message)
|
||||||
|
{
|
||||||
|
if( _debugEnabled )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
synchronized( this )
|
||||||
|
{
|
||||||
|
_stepCount++;
|
||||||
|
if( _stepTime > 0 )
|
||||||
|
{
|
||||||
|
wait( (int)_stepTime );
|
||||||
|
/** Can we resume execution or are we expected to wait? */
|
||||||
|
if( _waitUntilNotified )
|
||||||
|
{
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
// We have been notified
|
||||||
|
_waitUntilNotified = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( InterruptedException e )
|
||||||
|
{
|
||||||
|
update("Triangulation was interrupted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( _terminated )
|
||||||
|
{
|
||||||
|
throw new RuntimeException( "Triangulation process terminated before completion");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
_points.clear();
|
||||||
|
_terminated = false;
|
||||||
|
if( _debug != null )
|
||||||
|
{
|
||||||
|
_debug.clear();
|
||||||
|
}
|
||||||
|
_stepCount=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriangulationMode getTriangulationMode()
|
||||||
|
{
|
||||||
|
return _triangulationMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void waitUntilNotified(boolean b)
|
||||||
|
{
|
||||||
|
_waitUntilNotified = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void terminateTriangulation()
|
||||||
|
{
|
||||||
|
_terminated=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDebugEnabled()
|
||||||
|
{
|
||||||
|
return _debugEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void isDebugEnabled( boolean b );
|
||||||
|
|
||||||
|
public A getDebugContext()
|
||||||
|
{
|
||||||
|
return _debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPoints( List<TriangulationPoint> points )
|
||||||
|
{
|
||||||
|
_points.addAll( points );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package org.poly2tri.triangulation;
|
||||||
|
|
||||||
|
public abstract class TriangulationDebugContext
|
||||||
|
{
|
||||||
|
protected TriangulationContext<?> _tcx;
|
||||||
|
|
||||||
|
public TriangulationDebugContext( TriangulationContext<?> tcx )
|
||||||
|
{
|
||||||
|
_tcx = tcx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void clear();
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package org.poly2tri.triangulation;
|
||||||
|
|
||||||
|
public enum TriangulationMode
|
||||||
|
{
|
||||||
|
UNCONSTRAINED,CONSTRAINED,POLYGON;
|
||||||
|
}
|
||||||
112
src/main/java/org/poly2tri/triangulation/TriangulationPoint.java
Normal file
112
src/main/java/org/poly2tri/triangulation/TriangulationPoint.java
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.poly2tri.geometry.primitives.Point;
|
||||||
|
import org.poly2tri.triangulation.delaunay.sweep.DTSweepConstraint;
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class TriangulationPoint extends Point
|
||||||
|
{
|
||||||
|
// List of edges this point constitutes an upper ending point (CDT)
|
||||||
|
private ArrayList<DTSweepConstraint> edges;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "[" + getX() + "," + getY() + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract double getX();
|
||||||
|
public abstract double getY();
|
||||||
|
public abstract double getZ();
|
||||||
|
|
||||||
|
public abstract float getXf();
|
||||||
|
public abstract float getYf();
|
||||||
|
public abstract float getZf();
|
||||||
|
|
||||||
|
public abstract void set( double x, double y, double z );
|
||||||
|
|
||||||
|
public ArrayList<DTSweepConstraint> getEdges()
|
||||||
|
{
|
||||||
|
return edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEdge( DTSweepConstraint e )
|
||||||
|
{
|
||||||
|
if( edges == null )
|
||||||
|
{
|
||||||
|
edges = new ArrayList<DTSweepConstraint>();
|
||||||
|
}
|
||||||
|
edges.add( e );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasEdges()
|
||||||
|
{
|
||||||
|
return edges != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param p - edge destination point
|
||||||
|
* @return the edge from this point to given point
|
||||||
|
*/
|
||||||
|
public DTSweepConstraint getEdge( TriangulationPoint p )
|
||||||
|
{
|
||||||
|
for( DTSweepConstraint c : edges )
|
||||||
|
{
|
||||||
|
if( c.p == p )
|
||||||
|
{
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object obj)
|
||||||
|
{
|
||||||
|
if( obj instanceof TriangulationPoint )
|
||||||
|
{
|
||||||
|
TriangulationPoint p = (TriangulationPoint)obj;
|
||||||
|
return getX() == p.getX() && getY() == p.getY();
|
||||||
|
}
|
||||||
|
return super.equals( obj );
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
long bits = java.lang.Double.doubleToLongBits(getX());
|
||||||
|
bits ^= java.lang.Double.doubleToLongBits(getY()) * 31;
|
||||||
|
return (((int) bits) ^ ((int) (bits >> 32)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,341 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation;
|
||||||
|
|
||||||
|
import java.lang.Thread.State;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.poly2tri.Poly2Tri;
|
||||||
|
import org.poly2tri.geometry.polygon.Polygon;
|
||||||
|
import org.poly2tri.geometry.polygon.PolygonSet;
|
||||||
|
import org.poly2tri.triangulation.sets.ConstrainedPointSet;
|
||||||
|
import org.poly2tri.triangulation.sets.PointSet;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Thomas <20>hl<68>n, thahlen@gmail.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class TriangulationProcess implements Runnable
|
||||||
|
{
|
||||||
|
|
||||||
|
private final TriangulationAlgorithm _algorithm;
|
||||||
|
|
||||||
|
private TriangulationContext<?> _tcx;
|
||||||
|
private Thread _thread;
|
||||||
|
private boolean _isTerminated = false;
|
||||||
|
private int _pointCount = 0;
|
||||||
|
private long _timestamp = 0;
|
||||||
|
private double _triangulationTime = 0;
|
||||||
|
|
||||||
|
private boolean _awaitingTermination;
|
||||||
|
private boolean _restart = false;
|
||||||
|
|
||||||
|
private ArrayList<Triangulatable> _triangulations = new ArrayList<Triangulatable>();
|
||||||
|
|
||||||
|
private ArrayList<TriangulationProcessListener> _listeners = new ArrayList<TriangulationProcessListener>();
|
||||||
|
|
||||||
|
public void addListener( TriangulationProcessListener listener )
|
||||||
|
{
|
||||||
|
_listeners.add( listener );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeListener( TriangulationProcessListener listener )
|
||||||
|
{
|
||||||
|
_listeners.remove( listener );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearListeners()
|
||||||
|
{
|
||||||
|
_listeners.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify all listeners of this new event
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
private void sendEvent( TriangulationProcessEvent event )
|
||||||
|
{
|
||||||
|
for( TriangulationProcessListener l : _listeners )
|
||||||
|
{
|
||||||
|
l.triangulationEvent( event, _tcx.getTriangulatable() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStepCount()
|
||||||
|
{
|
||||||
|
return _tcx.getStepCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimestamp()
|
||||||
|
{
|
||||||
|
return _timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getTriangulationTime()
|
||||||
|
{
|
||||||
|
return _triangulationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses SweepLine algorithm by default
|
||||||
|
* @param algorithm
|
||||||
|
*/
|
||||||
|
public TriangulationProcess()
|
||||||
|
{
|
||||||
|
this( TriangulationAlgorithm.DTSweep );
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriangulationProcess( TriangulationAlgorithm algorithm )
|
||||||
|
{
|
||||||
|
_algorithm = algorithm;
|
||||||
|
_tcx = Poly2Tri.createContext( algorithm );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This retriangulates same set as previous triangulation
|
||||||
|
* useful if you want to do consecutive triangulations with
|
||||||
|
* same data. Like when you when you want to do performance
|
||||||
|
* tests.
|
||||||
|
*/
|
||||||
|
// public void triangulate()
|
||||||
|
// {
|
||||||
|
// start();
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triangulate a PointSet with eventual constraints
|
||||||
|
*
|
||||||
|
* @param cps
|
||||||
|
*/
|
||||||
|
public void triangulate( PointSet ps )
|
||||||
|
{
|
||||||
|
_triangulations.clear();
|
||||||
|
_triangulations.add( ps );
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triangulate a PointSet with eventual constraints
|
||||||
|
*
|
||||||
|
* @param cps
|
||||||
|
*/
|
||||||
|
public void triangulate( ConstrainedPointSet cps )
|
||||||
|
{
|
||||||
|
_triangulations.clear();
|
||||||
|
_triangulations.add( cps );
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triangulate a PolygonSet
|
||||||
|
*
|
||||||
|
* @param ps
|
||||||
|
*/
|
||||||
|
public void triangulate( PolygonSet ps )
|
||||||
|
{
|
||||||
|
_triangulations.clear();
|
||||||
|
_triangulations.addAll( ps.getPolygons() );
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triangulate a Polygon
|
||||||
|
*
|
||||||
|
* @param ps
|
||||||
|
*/
|
||||||
|
public void triangulate( Polygon polygon )
|
||||||
|
{
|
||||||
|
_triangulations.clear();
|
||||||
|
_triangulations.add( polygon );
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triangulate a List of Triangulatables
|
||||||
|
*
|
||||||
|
* @param ps
|
||||||
|
*/
|
||||||
|
public void triangulate( List<Triangulatable> list )
|
||||||
|
{
|
||||||
|
_triangulations.clear();
|
||||||
|
_triangulations.addAll( list );
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void start()
|
||||||
|
{
|
||||||
|
if( _thread == null || _thread.getState() == State.TERMINATED )
|
||||||
|
{
|
||||||
|
_isTerminated = false;
|
||||||
|
_thread = new Thread( this, _algorithm.name() + "." + _tcx.getTriangulationMode() );
|
||||||
|
_thread.start();
|
||||||
|
sendEvent( TriangulationProcessEvent.Started );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Triangulation already running. Terminate it so we can start a new
|
||||||
|
shutdown();
|
||||||
|
_restart = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWaiting()
|
||||||
|
{
|
||||||
|
if( _thread != null && _thread.getState() == State.WAITING )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
_pointCount=0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
long time = System.nanoTime();
|
||||||
|
for( Triangulatable t : _triangulations )
|
||||||
|
{
|
||||||
|
_tcx.clear();
|
||||||
|
_tcx.prepareTriangulation( t );
|
||||||
|
_pointCount += _tcx._points.size();
|
||||||
|
Poly2Tri.triangulate( _tcx );
|
||||||
|
}
|
||||||
|
_triangulationTime = ( System.nanoTime() - time ) / 1e6;
|
||||||
|
sendEvent( TriangulationProcessEvent.Done );
|
||||||
|
}
|
||||||
|
catch( RuntimeException e )
|
||||||
|
{
|
||||||
|
if( _awaitingTermination )
|
||||||
|
{
|
||||||
|
_awaitingTermination = false;
|
||||||
|
sendEvent( TriangulationProcessEvent.Aborted );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
sendEvent( TriangulationProcessEvent.Failed );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( Exception e )
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
sendEvent( TriangulationProcessEvent.Failed );
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_timestamp = System.currentTimeMillis();
|
||||||
|
_isTerminated = true;
|
||||||
|
_thread = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Autostart a new triangulation?
|
||||||
|
if( _restart )
|
||||||
|
{
|
||||||
|
_restart = false;
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resume()
|
||||||
|
{
|
||||||
|
if( _thread != null )
|
||||||
|
{
|
||||||
|
// Only force a resume when process is waiting for a notification
|
||||||
|
if( _thread.getState() == State.WAITING )
|
||||||
|
{
|
||||||
|
synchronized( _tcx )
|
||||||
|
{
|
||||||
|
_tcx.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( _thread.getState() == State.TIMED_WAITING )
|
||||||
|
{
|
||||||
|
_tcx.waitUntilNotified( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown()
|
||||||
|
{
|
||||||
|
_awaitingTermination = true;
|
||||||
|
_tcx.terminateTriangulation();
|
||||||
|
resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriangulationContext<?> getContext()
|
||||||
|
{
|
||||||
|
return _tcx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDone()
|
||||||
|
{
|
||||||
|
return _isTerminated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestRead()
|
||||||
|
{
|
||||||
|
_tcx.waitUntilNotified( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReadable()
|
||||||
|
{
|
||||||
|
if( _thread == null )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
synchronized( _thread )
|
||||||
|
{
|
||||||
|
if( _thread.getState() == State.WAITING )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if( _thread.getState() == State.TIMED_WAITING )
|
||||||
|
{
|
||||||
|
// Make sure that it stays readable
|
||||||
|
_tcx.waitUntilNotified( true );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPointCount()
|
||||||
|
{
|
||||||
|
return _pointCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation;
|
||||||
|
|
||||||
|
public enum TriangulationProcessEvent
|
||||||
|
{
|
||||||
|
Started,Waiting,Failed,Aborted,Done
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation;
|
||||||
|
|
||||||
|
public interface TriangulationProcessListener
|
||||||
|
{
|
||||||
|
public void triangulationEvent( TriangulationProcessEvent e, Triangulatable unit );
|
||||||
|
}
|
||||||
213
src/main/java/org/poly2tri/triangulation/TriangulationUtil.java
Normal file
213
src/main/java/org/poly2tri/triangulation/TriangulationUtil.java
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/package org.poly2tri.triangulation;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Thomas <20>hl<68>n, thahlen@gmail.com
|
||||||
|
*/
|
||||||
|
public class TriangulationUtil
|
||||||
|
{
|
||||||
|
public final static double EPSILON = 1e-12;
|
||||||
|
|
||||||
|
// Returns triangle circumcircle point and radius
|
||||||
|
// public static Tuple2<TPoint, Double> circumCircle( TPoint a, TPoint b, TPoint c )
|
||||||
|
// {
|
||||||
|
// double A = det( a, b, c );
|
||||||
|
// double C = detC( a, b, c );
|
||||||
|
//
|
||||||
|
// double sa = a.getX() * a.getX() + a.getY() * a.getY();
|
||||||
|
// double sb = b.getX() * b.getX() + b.getY() * b.getY();
|
||||||
|
// double sc = c.getX() * c.getX() + c.getY() * c.getY();
|
||||||
|
//
|
||||||
|
// TPoint bx1 = new TPoint( sa, a.getY() );
|
||||||
|
// TPoint bx2 = new TPoint( sb, b.getY() );
|
||||||
|
// TPoint bx3 = new TPoint( sc, c.getY() );
|
||||||
|
// double bx = det( bx1, bx2, bx3 );
|
||||||
|
//
|
||||||
|
// TPoint by1 = new TPoint( sa, a.getX() );
|
||||||
|
// TPoint by2 = new TPoint( sb, b.getX() );
|
||||||
|
// TPoint by3 = new TPoint( sc, c.getX() );
|
||||||
|
// double by = det( by1, by2, by3 );
|
||||||
|
//
|
||||||
|
// double x = bx / ( 2 * A );
|
||||||
|
// double y = by / ( 2 * A );
|
||||||
|
//
|
||||||
|
// TPoint center = new TPoint( x, y );
|
||||||
|
// double radius = Math.sqrt( bx * bx + by * by - 4 * A * C ) / ( 2 * Math.abs( A ) );
|
||||||
|
//
|
||||||
|
// return new Tuple2<TPoint, Double>( center, radius );
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <b>Requirement</b>:<br>
|
||||||
|
* 1. a,b and c form a triangle.<br>
|
||||||
|
* 2. a and d is know to be on opposite side of bc<br>
|
||||||
|
* <pre>
|
||||||
|
* a
|
||||||
|
* +
|
||||||
|
* / \
|
||||||
|
* / \
|
||||||
|
* b/ \c
|
||||||
|
* +-------+
|
||||||
|
* / B \
|
||||||
|
* / \
|
||||||
|
* </pre>
|
||||||
|
* <b>Fact</b>: d has to be in area B to have a chance to be inside the circle formed by
|
||||||
|
* a,b and c<br>
|
||||||
|
* d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW<br>
|
||||||
|
* This preknowledge gives us a way to optimize the incircle test
|
||||||
|
* @param a - triangle point, opposite d
|
||||||
|
* @param b - triangle point
|
||||||
|
* @param c - triangle point
|
||||||
|
* @param d - point opposite a
|
||||||
|
* @return true if d is inside circle, false if on circle edge
|
||||||
|
*/
|
||||||
|
public static boolean smartIncircle( final TriangulationPoint pa,
|
||||||
|
final TriangulationPoint pb,
|
||||||
|
final TriangulationPoint pc,
|
||||||
|
final TriangulationPoint pd )
|
||||||
|
{
|
||||||
|
final double pdx = pd.getX();
|
||||||
|
final double pdy = pd.getY();
|
||||||
|
final double adx = pa.getX() - pdx;
|
||||||
|
final double ady = pa.getY() - pdy;
|
||||||
|
final double bdx = pb.getX() - pdx;
|
||||||
|
final double bdy = pb.getY() - pdy;
|
||||||
|
|
||||||
|
final double adxbdy = adx * bdy;
|
||||||
|
final double bdxady = bdx * ady;
|
||||||
|
final double oabd = adxbdy - bdxady;
|
||||||
|
// oabd = orient2d(pa,pb,pd);
|
||||||
|
if( oabd <= 0 )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final double cdx = pc.getX() - pdx;
|
||||||
|
final double cdy = pc.getY() - pdy;
|
||||||
|
|
||||||
|
final double cdxady = cdx * ady;
|
||||||
|
final double adxcdy = adx * cdy;
|
||||||
|
final double ocad = cdxady - adxcdy;
|
||||||
|
// ocad = orient2d(pc,pa,pd);
|
||||||
|
if( ocad <= 0 )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final double bdxcdy = bdx * cdy;
|
||||||
|
final double cdxbdy = cdx * bdy;
|
||||||
|
|
||||||
|
final double alift = adx * adx + ady * ady;
|
||||||
|
final double blift = bdx * bdx + bdy * bdy;
|
||||||
|
final double clift = cdx * cdx + cdy * cdy;
|
||||||
|
|
||||||
|
final double det = alift * ( bdxcdy - cdxbdy ) + blift * ocad + clift * oabd;
|
||||||
|
|
||||||
|
return det > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see smartIncircle
|
||||||
|
* @param pa
|
||||||
|
* @param pb
|
||||||
|
* @param pc
|
||||||
|
* @param pd
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean inScanArea( final TriangulationPoint pa,
|
||||||
|
final TriangulationPoint pb,
|
||||||
|
final TriangulationPoint pc,
|
||||||
|
final TriangulationPoint pd )
|
||||||
|
{
|
||||||
|
final double pdx = pd.getX();
|
||||||
|
final double pdy = pd.getY();
|
||||||
|
final double adx = pa.getX() - pdx;
|
||||||
|
final double ady = pa.getY() - pdy;
|
||||||
|
final double bdx = pb.getX() - pdx;
|
||||||
|
final double bdy = pb.getY() - pdy;
|
||||||
|
|
||||||
|
final double adxbdy = adx * bdy;
|
||||||
|
final double bdxady = bdx * ady;
|
||||||
|
final double oabd = adxbdy - bdxady;
|
||||||
|
// oabd = orient2d(pa,pb,pd);
|
||||||
|
if( oabd <= 0 )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final double cdx = pc.getX() - pdx;
|
||||||
|
final double cdy = pc.getY() - pdy;
|
||||||
|
|
||||||
|
final double cdxady = cdx * ady;
|
||||||
|
final double adxcdy = adx * cdy;
|
||||||
|
final double ocad = cdxady - adxcdy;
|
||||||
|
// ocad = orient2d(pc,pa,pd);
|
||||||
|
if( ocad <= 0 )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forumla to calculate signed area<br>
|
||||||
|
* Positive if CCW<br>
|
||||||
|
* Negative if CW<br>
|
||||||
|
* 0 if collinear<br>
|
||||||
|
* <pre>
|
||||||
|
* A[P1,P2,P3] = (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
|
||||||
|
* = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public static Orientation orient2d( TriangulationPoint pa,
|
||||||
|
TriangulationPoint pb,
|
||||||
|
TriangulationPoint pc )
|
||||||
|
{
|
||||||
|
double detleft = ( pa.getX() - pc.getX() ) * ( pb.getY() - pc.getY() );
|
||||||
|
double detright = ( pa.getY() - pc.getY() ) * ( pb.getX() - pc.getX() );
|
||||||
|
double val = detleft - detright;
|
||||||
|
if( val > -EPSILON && val < EPSILON )
|
||||||
|
{
|
||||||
|
return Orientation.Collinear;
|
||||||
|
}
|
||||||
|
else if( val > 0 )
|
||||||
|
{
|
||||||
|
return Orientation.CCW;
|
||||||
|
}
|
||||||
|
return Orientation.CW;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Orientation
|
||||||
|
{
|
||||||
|
CW,CCW,Collinear;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,685 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation.delaunay;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.poly2tri.triangulation.TriangulationPoint;
|
||||||
|
import org.poly2tri.triangulation.delaunay.sweep.DTSweepConstraint;
|
||||||
|
import org.poly2tri.triangulation.point.TPoint;
|
||||||
|
|
||||||
|
|
||||||
|
public class DelaunayTriangle
|
||||||
|
{
|
||||||
|
|
||||||
|
/** Neighbor pointers */
|
||||||
|
public final DelaunayTriangle[] neighbors = new DelaunayTriangle[3];
|
||||||
|
/** Flags to determine if an edge is a Constrained edge */
|
||||||
|
public final boolean[] cEdge = new boolean[] { false, false, false };
|
||||||
|
/** Flags to determine if an edge is a Delauney edge */
|
||||||
|
public final boolean[] dEdge = new boolean[] { false, false, false };
|
||||||
|
/** Has this triangle been marked as an interior triangle? */
|
||||||
|
protected boolean interior = false;
|
||||||
|
|
||||||
|
public final TriangulationPoint[] points = new TriangulationPoint[3];
|
||||||
|
|
||||||
|
public DelaunayTriangle( TriangulationPoint p1, TriangulationPoint p2, TriangulationPoint p3 )
|
||||||
|
{
|
||||||
|
points[0] = p1;
|
||||||
|
points[1] = p2;
|
||||||
|
points[2] = p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int index( TriangulationPoint p )
|
||||||
|
{
|
||||||
|
if( p == points[0] )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if( p == points[1] )
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if( p == points[2] )
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Calling index with a point that doesn't exist in triangle");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int indexCW( TriangulationPoint p )
|
||||||
|
{
|
||||||
|
int index = index(p);
|
||||||
|
switch( index )
|
||||||
|
{
|
||||||
|
case 0: return 2;
|
||||||
|
case 1: return 0;
|
||||||
|
default: return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int indexCCW( TriangulationPoint p )
|
||||||
|
{
|
||||||
|
int index = index(p);
|
||||||
|
switch( index )
|
||||||
|
{
|
||||||
|
case 0: return 1;
|
||||||
|
case 1: return 2;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains( TriangulationPoint p )
|
||||||
|
{
|
||||||
|
return ( p == points[0] || p == points[1] || p == points[2] );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains( DTSweepConstraint e )
|
||||||
|
{
|
||||||
|
return ( contains( e.p ) && contains( e.q ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains( TriangulationPoint p, TriangulationPoint q )
|
||||||
|
{
|
||||||
|
return ( contains( p ) && contains( q ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update neighbor pointers
|
||||||
|
private void markNeighbor( TriangulationPoint p1,
|
||||||
|
TriangulationPoint p2,
|
||||||
|
DelaunayTriangle t )
|
||||||
|
{
|
||||||
|
if( ( p1 == points[2] && p2 == points[1] ) || ( p1 == points[1] && p2 == points[2] ) )
|
||||||
|
{
|
||||||
|
neighbors[0] = t;
|
||||||
|
}
|
||||||
|
else if( ( p1 == points[0] && p2 == points[2] ) || ( p1 == points[2] && p2 == points[0] ) )
|
||||||
|
{
|
||||||
|
neighbors[1] = t;
|
||||||
|
}
|
||||||
|
else if( ( p1 == points[0] && p2 == points[1] ) || ( p1 == points[1] && p2 == points[0] ) )
|
||||||
|
{
|
||||||
|
neighbors[2] = t;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// throw new Exception("Neighbor error, please report!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exhaustive search to update neighbor pointers */
|
||||||
|
public void markNeighbor( DelaunayTriangle t )
|
||||||
|
{
|
||||||
|
if( t.contains( points[1], points[2] ) )
|
||||||
|
{
|
||||||
|
neighbors[0] = t;
|
||||||
|
t.markNeighbor( points[1], points[2], this );
|
||||||
|
}
|
||||||
|
else if( t.contains( points[0], points[2] ) )
|
||||||
|
{
|
||||||
|
neighbors[1] = t;
|
||||||
|
t.markNeighbor( points[0], points[2], this );
|
||||||
|
}
|
||||||
|
else if( t.contains( points[0], points[1] ) )
|
||||||
|
{
|
||||||
|
neighbors[2] = t;
|
||||||
|
t.markNeighbor( points[0], points[1], this );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearNeighbors()
|
||||||
|
{
|
||||||
|
neighbors[0] = neighbors[1] = neighbors[2] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearNeighbor( DelaunayTriangle triangle )
|
||||||
|
{
|
||||||
|
if( neighbors[0] == triangle )
|
||||||
|
{
|
||||||
|
neighbors[0] = null;
|
||||||
|
}
|
||||||
|
else if( neighbors[1] == triangle )
|
||||||
|
{
|
||||||
|
neighbors[1] = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors[2] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all references to all other triangles and points
|
||||||
|
*/
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
DelaunayTriangle t;
|
||||||
|
for( int i=0; i<3; i++ )
|
||||||
|
{
|
||||||
|
t = neighbors[i];
|
||||||
|
if( t != null )
|
||||||
|
{
|
||||||
|
t.clearNeighbor( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clearNeighbors();
|
||||||
|
points[0]=points[1]=points[2]=null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param t - opposite triangle
|
||||||
|
* @param p - the point in t that isn't shared between the triangles
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public TriangulationPoint oppositePoint( DelaunayTriangle t, TriangulationPoint p )
|
||||||
|
{
|
||||||
|
assert t != this : "self-pointer error";
|
||||||
|
return pointCW( t.pointCW(p) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// The neighbor clockwise to given point
|
||||||
|
public DelaunayTriangle neighborCW( TriangulationPoint point )
|
||||||
|
{
|
||||||
|
if( point == points[0] )
|
||||||
|
{
|
||||||
|
return neighbors[1];
|
||||||
|
}
|
||||||
|
else if( point == points[1] )
|
||||||
|
{
|
||||||
|
return neighbors[2];
|
||||||
|
}
|
||||||
|
return neighbors[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// The neighbor counter-clockwise to given point
|
||||||
|
public DelaunayTriangle neighborCCW( TriangulationPoint point )
|
||||||
|
{
|
||||||
|
if( point == points[0] )
|
||||||
|
{
|
||||||
|
return neighbors[2];
|
||||||
|
}
|
||||||
|
else if( point == points[1] )
|
||||||
|
{
|
||||||
|
return neighbors[0];
|
||||||
|
}
|
||||||
|
return neighbors[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// The neighbor across to given point
|
||||||
|
public DelaunayTriangle neighborAcross( TriangulationPoint opoint )
|
||||||
|
{
|
||||||
|
if( opoint == points[0] )
|
||||||
|
{
|
||||||
|
return neighbors[0];
|
||||||
|
}
|
||||||
|
else if( opoint == points[1] )
|
||||||
|
{
|
||||||
|
return neighbors[1];
|
||||||
|
}
|
||||||
|
return neighbors[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// The point counter-clockwise to given point
|
||||||
|
public TriangulationPoint pointCCW( TriangulationPoint point )
|
||||||
|
{
|
||||||
|
if( point == points[0] )
|
||||||
|
{
|
||||||
|
return points[1];
|
||||||
|
}
|
||||||
|
else if( point == points[1] )
|
||||||
|
{
|
||||||
|
return points[2];
|
||||||
|
}
|
||||||
|
else if( point == points[2] )
|
||||||
|
{
|
||||||
|
return points[0];
|
||||||
|
}
|
||||||
|
throw new RuntimeException("[FIXME] point location error");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The point counter-clockwise to given point
|
||||||
|
public TriangulationPoint pointCW( TriangulationPoint point )
|
||||||
|
{
|
||||||
|
if( point == points[0] )
|
||||||
|
{
|
||||||
|
return points[2];
|
||||||
|
}
|
||||||
|
else if( point == points[1] )
|
||||||
|
{
|
||||||
|
return points[0];
|
||||||
|
}
|
||||||
|
else if( point == points[2] )
|
||||||
|
{
|
||||||
|
return points[1];
|
||||||
|
}
|
||||||
|
throw new RuntimeException("[FIXME] point location error");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Legalize triangle by rotating clockwise around oPoint
|
||||||
|
public void legalize( TriangulationPoint oPoint, TriangulationPoint nPoint )
|
||||||
|
{
|
||||||
|
if( oPoint == points[0] )
|
||||||
|
{
|
||||||
|
points[1] = points[0];
|
||||||
|
points[0] = points[2];
|
||||||
|
points[2] = nPoint;
|
||||||
|
}
|
||||||
|
else if( oPoint == points[1] )
|
||||||
|
{
|
||||||
|
points[2] = points[1];
|
||||||
|
points[1] = points[0];
|
||||||
|
points[0] = nPoint;
|
||||||
|
}
|
||||||
|
else if( oPoint == points[2] )
|
||||||
|
{
|
||||||
|
points[0] = points[2];
|
||||||
|
points[2] = points[1];
|
||||||
|
points[1] = nPoint;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RuntimeException("legalization bug");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printDebug()
|
||||||
|
{
|
||||||
|
System.out.println( points[0] + "," + points[1] + "," + points[2] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finalize edge marking
|
||||||
|
public void markNeighborEdges()
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 3; i++ )
|
||||||
|
{
|
||||||
|
if( cEdge[i] )
|
||||||
|
{
|
||||||
|
switch( i )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if( neighbors[0] != null )
|
||||||
|
neighbors[0].markConstrainedEdge( points[1], points[2] );
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if( neighbors[1] != null )
|
||||||
|
neighbors[1].markConstrainedEdge( points[0], points[2] );
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if( neighbors[2] != null )
|
||||||
|
neighbors[2].markConstrainedEdge( points[0], points[1] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markEdge( DelaunayTriangle triangle )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 3; i++ )
|
||||||
|
{
|
||||||
|
if( cEdge[i] )
|
||||||
|
{
|
||||||
|
switch( i )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
triangle.markConstrainedEdge( points[1], points[2] );
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
triangle.markConstrainedEdge( points[0], points[2] );
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
triangle.markConstrainedEdge( points[0], points[1] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markEdge( ArrayList<DelaunayTriangle> tList )
|
||||||
|
{
|
||||||
|
|
||||||
|
for( DelaunayTriangle t : tList )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 3; i++ )
|
||||||
|
{
|
||||||
|
if( t.cEdge[i] )
|
||||||
|
{
|
||||||
|
switch( i )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
markConstrainedEdge( t.points[1], t.points[2] );
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
markConstrainedEdge( t.points[0], t.points[2] );
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
markConstrainedEdge( t.points[0], t.points[1] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markConstrainedEdge( int index )
|
||||||
|
{
|
||||||
|
cEdge[index] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markConstrainedEdge( DTSweepConstraint edge )
|
||||||
|
{
|
||||||
|
markConstrainedEdge( edge.p, edge.q );
|
||||||
|
if( ( edge.q == points[0] && edge.p == points[1] )
|
||||||
|
|| ( edge.q == points[1] && edge.p == points[0] ) )
|
||||||
|
{
|
||||||
|
cEdge[2] = true;
|
||||||
|
}
|
||||||
|
else if( ( edge.q == points[0] && edge.p == points[2] )
|
||||||
|
|| ( edge.q == points[2] && edge.p == points[0] ) )
|
||||||
|
{
|
||||||
|
cEdge[1] = true;
|
||||||
|
}
|
||||||
|
else if( ( edge.q == points[1] && edge.p == points[2] )
|
||||||
|
|| ( edge.q == points[2] && edge.p == points[1] ) )
|
||||||
|
{
|
||||||
|
cEdge[0] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark edge as constrained
|
||||||
|
public void markConstrainedEdge( TriangulationPoint p, TriangulationPoint q )
|
||||||
|
{
|
||||||
|
if( ( q == points[0] && p == points[1] ) || ( q == points[1] && p == points[0] ) )
|
||||||
|
{
|
||||||
|
cEdge[2] = true;
|
||||||
|
}
|
||||||
|
else if( ( q == points[0] && p == points[2] ) || ( q == points[2] && p == points[0] ) )
|
||||||
|
{
|
||||||
|
cEdge[1] = true;
|
||||||
|
}
|
||||||
|
else if( ( q == points[1] && p == points[2] ) || ( q == points[2] && p == points[1] ) )
|
||||||
|
{
|
||||||
|
cEdge[0] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double area()
|
||||||
|
{
|
||||||
|
double a = (points[0].getX() - points[2].getX())*(points[1].getY() - points[0].getY());
|
||||||
|
double b = (points[0].getX() - points[1].getX())*(points[2].getY() - points[0].getY());
|
||||||
|
|
||||||
|
return 0.5*Math.abs( a - b );
|
||||||
|
}
|
||||||
|
|
||||||
|
public TPoint centroid()
|
||||||
|
{
|
||||||
|
double cx = ( points[0].getX() + points[1].getX() + points[2].getX() ) / 3d;
|
||||||
|
double cy = ( points[0].getY() + points[1].getY() + points[2].getY() ) / 3d;
|
||||||
|
return new TPoint( cx, cy );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the neighbor that share this edge
|
||||||
|
*
|
||||||
|
* @param constrainedEdge
|
||||||
|
* @return index of the shared edge or -1 if edge isn't shared
|
||||||
|
*/
|
||||||
|
public int edgeIndex( TriangulationPoint p1, TriangulationPoint p2 )
|
||||||
|
{
|
||||||
|
if( points[0] == p1 )
|
||||||
|
{
|
||||||
|
if( points[1] == p2 )
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
else if( points[2] == p2 )
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( points[1] == p1 )
|
||||||
|
{
|
||||||
|
if( points[2] == p2 )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if( points[0] == p2 )
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( points[2] == p1 )
|
||||||
|
{
|
||||||
|
if( points[0] == p2 )
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if( points[1] == p2 )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getConstrainedEdgeCCW( TriangulationPoint p )
|
||||||
|
{
|
||||||
|
if( p == points[0] )
|
||||||
|
{
|
||||||
|
return cEdge[2];
|
||||||
|
}
|
||||||
|
else if( p == points[1] )
|
||||||
|
{
|
||||||
|
return cEdge[0];
|
||||||
|
}
|
||||||
|
return cEdge[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getConstrainedEdgeCW( TriangulationPoint p )
|
||||||
|
{
|
||||||
|
if( p == points[0] )
|
||||||
|
{
|
||||||
|
return cEdge[1];
|
||||||
|
}
|
||||||
|
else if( p == points[1] )
|
||||||
|
{
|
||||||
|
return cEdge[2];
|
||||||
|
}
|
||||||
|
return cEdge[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getConstrainedEdgeAcross( TriangulationPoint p )
|
||||||
|
{
|
||||||
|
if( p == points[0] )
|
||||||
|
{
|
||||||
|
return cEdge[0];
|
||||||
|
}
|
||||||
|
else if( p == points[1] )
|
||||||
|
{
|
||||||
|
return cEdge[1];
|
||||||
|
}
|
||||||
|
return cEdge[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConstrainedEdgeCCW( TriangulationPoint p, boolean ce )
|
||||||
|
{
|
||||||
|
if( p == points[0] )
|
||||||
|
{
|
||||||
|
cEdge[2] = ce;
|
||||||
|
}
|
||||||
|
else if( p == points[1] )
|
||||||
|
{
|
||||||
|
cEdge[0] = ce;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cEdge[1] = ce;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConstrainedEdgeCW( TriangulationPoint p, boolean ce )
|
||||||
|
{
|
||||||
|
if( p == points[0] )
|
||||||
|
{
|
||||||
|
cEdge[1] = ce;
|
||||||
|
}
|
||||||
|
else if( p == points[1] )
|
||||||
|
{
|
||||||
|
cEdge[2] = ce;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cEdge[0] = ce;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConstrainedEdgeAcross( TriangulationPoint p, boolean ce )
|
||||||
|
{
|
||||||
|
if( p == points[0] )
|
||||||
|
{
|
||||||
|
cEdge[0] = ce;
|
||||||
|
}
|
||||||
|
else if( p == points[1] )
|
||||||
|
{
|
||||||
|
cEdge[1] = ce;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cEdge[2] = ce;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getDelunayEdgeCCW( TriangulationPoint p )
|
||||||
|
{
|
||||||
|
if( p == points[0] )
|
||||||
|
{
|
||||||
|
return dEdge[2];
|
||||||
|
}
|
||||||
|
else if( p == points[1] )
|
||||||
|
{
|
||||||
|
return dEdge[0];
|
||||||
|
}
|
||||||
|
return dEdge[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getDelunayEdgeCW( TriangulationPoint p )
|
||||||
|
{
|
||||||
|
if( p == points[0] )
|
||||||
|
{
|
||||||
|
return dEdge[1];
|
||||||
|
}
|
||||||
|
else if( p == points[1] )
|
||||||
|
{
|
||||||
|
return dEdge[2];
|
||||||
|
}
|
||||||
|
return dEdge[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getDelunayEdgeAcross( TriangulationPoint p )
|
||||||
|
{
|
||||||
|
if( p == points[0] )
|
||||||
|
{
|
||||||
|
return dEdge[0];
|
||||||
|
}
|
||||||
|
else if( p == points[1] )
|
||||||
|
{
|
||||||
|
return dEdge[1];
|
||||||
|
}
|
||||||
|
return dEdge[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDelunayEdgeCCW( TriangulationPoint p, boolean e )
|
||||||
|
{
|
||||||
|
if( p == points[0] )
|
||||||
|
{
|
||||||
|
dEdge[2] = e;
|
||||||
|
}
|
||||||
|
else if( p == points[1] )
|
||||||
|
{
|
||||||
|
dEdge[0] = e;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dEdge[1] = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDelunayEdgeCW( TriangulationPoint p, boolean e )
|
||||||
|
{
|
||||||
|
if( p == points[0] )
|
||||||
|
{
|
||||||
|
dEdge[1] = e;
|
||||||
|
}
|
||||||
|
else if( p == points[1] )
|
||||||
|
{
|
||||||
|
dEdge[2] = e;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dEdge[0] = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDelunayEdgeAcross( TriangulationPoint p, boolean e )
|
||||||
|
{
|
||||||
|
if( p == points[0] )
|
||||||
|
{
|
||||||
|
dEdge[0] = e;
|
||||||
|
}
|
||||||
|
else if( p == points[1] )
|
||||||
|
{
|
||||||
|
dEdge[1] = e;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dEdge[2] = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearDelunayEdges()
|
||||||
|
{
|
||||||
|
dEdge[0] = false;
|
||||||
|
dEdge[1] = false;
|
||||||
|
dEdge[2] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInterior()
|
||||||
|
{
|
||||||
|
return interior;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void isInterior( boolean b )
|
||||||
|
{
|
||||||
|
interior = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation.delaunay.sweep;
|
||||||
|
|
||||||
|
import org.poly2tri.triangulation.TriangulationPoint;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Thomas <20>hlen (thahlen@gmail.com)
|
||||||
|
*/
|
||||||
|
public class AdvancingFront
|
||||||
|
{
|
||||||
|
public AdvancingFrontNode head;
|
||||||
|
public AdvancingFrontNode tail;
|
||||||
|
protected AdvancingFrontNode search;
|
||||||
|
|
||||||
|
public AdvancingFront( AdvancingFrontNode head, AdvancingFrontNode tail )
|
||||||
|
{
|
||||||
|
this.head = head;
|
||||||
|
this.tail = tail;
|
||||||
|
this.search = head;
|
||||||
|
addNode( head );
|
||||||
|
addNode( tail );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addNode( AdvancingFrontNode node )
|
||||||
|
{
|
||||||
|
// _searchTree.put( node.key, node );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeNode( AdvancingFrontNode node )
|
||||||
|
{
|
||||||
|
// _searchTree.delete( node.key );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
AdvancingFrontNode node = head;
|
||||||
|
while( node != tail )
|
||||||
|
{
|
||||||
|
sb.append( node.point.getX() ).append( "->" );
|
||||||
|
node = node.next;
|
||||||
|
}
|
||||||
|
sb.append( tail.point.getX() );
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final AdvancingFrontNode findSearchNode( double x )
|
||||||
|
{
|
||||||
|
// TODO: implement BST index
|
||||||
|
return search;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We use a balancing tree to locate a node smaller or equal to
|
||||||
|
* given key value
|
||||||
|
*
|
||||||
|
* @param x
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public AdvancingFrontNode locateNode( TriangulationPoint point )
|
||||||
|
{
|
||||||
|
return locateNode( point.getX() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private AdvancingFrontNode locateNode( double x )
|
||||||
|
{
|
||||||
|
AdvancingFrontNode node = findSearchNode(x);
|
||||||
|
if( x < node.value )
|
||||||
|
{
|
||||||
|
while( (node = node.prev) != null )
|
||||||
|
{
|
||||||
|
if( x >= node.value )
|
||||||
|
{
|
||||||
|
search = node;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while( (node = node.next) != null )
|
||||||
|
{
|
||||||
|
if( x < node.value )
|
||||||
|
{
|
||||||
|
search = node.prev;
|
||||||
|
return node.prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This implementation will use simple node traversal algorithm to find
|
||||||
|
* a point on the front
|
||||||
|
*
|
||||||
|
* @param point
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public AdvancingFrontNode locatePoint( final TriangulationPoint point )
|
||||||
|
{
|
||||||
|
final double px = point.getX();
|
||||||
|
AdvancingFrontNode node = findSearchNode(px);
|
||||||
|
final double nx = node.point.getX();
|
||||||
|
|
||||||
|
if( px == nx )
|
||||||
|
{
|
||||||
|
if( point != node.point )
|
||||||
|
{
|
||||||
|
// We might have two nodes with same x value for a short time
|
||||||
|
if( point == node.prev.point )
|
||||||
|
{
|
||||||
|
node = node.prev;
|
||||||
|
}
|
||||||
|
else if( point == node.next.point )
|
||||||
|
{
|
||||||
|
node = node.next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RuntimeException( "Failed to find Node for given afront point");
|
||||||
|
// node = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( px < nx )
|
||||||
|
{
|
||||||
|
while( (node = node.prev) != null )
|
||||||
|
{
|
||||||
|
if( point == node.point )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while( (node = node.next) != null )
|
||||||
|
{
|
||||||
|
if( point == node.point )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
search = node;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package org.poly2tri.triangulation.delaunay.sweep;
|
||||||
|
|
||||||
|
public class AdvancingFrontIndex<A>
|
||||||
|
{
|
||||||
|
double _min,_max;
|
||||||
|
IndexNode<A> _root;
|
||||||
|
|
||||||
|
public AdvancingFrontIndex( double min, double max, int depth )
|
||||||
|
{
|
||||||
|
if( depth > 5 ) depth = 5;
|
||||||
|
_root = createIndex( depth );
|
||||||
|
}
|
||||||
|
|
||||||
|
private IndexNode<A> createIndex( int n )
|
||||||
|
{
|
||||||
|
IndexNode<A> node = null;
|
||||||
|
if( n > 0 )
|
||||||
|
{
|
||||||
|
node = new IndexNode<A>();
|
||||||
|
node.bigger = createIndex( n-1 );
|
||||||
|
node.smaller = createIndex( n-1 );
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public A fetchAndRemoveIndex( A key )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public A fetchAndInsertIndex( A key )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
class IndexNode<A>
|
||||||
|
{
|
||||||
|
A value;
|
||||||
|
IndexNode<A> smaller;
|
||||||
|
IndexNode<A> bigger;
|
||||||
|
double range;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation.delaunay.sweep;
|
||||||
|
|
||||||
|
import org.poly2tri.triangulation.TriangulationPoint;
|
||||||
|
import org.poly2tri.triangulation.delaunay.DelaunayTriangle;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class AdvancingFrontNode
|
||||||
|
{
|
||||||
|
protected AdvancingFrontNode next = null;
|
||||||
|
protected AdvancingFrontNode prev = null;
|
||||||
|
|
||||||
|
protected final Double key; // XXX: BST
|
||||||
|
protected final double value;
|
||||||
|
protected final TriangulationPoint point;
|
||||||
|
protected DelaunayTriangle triangle;
|
||||||
|
|
||||||
|
public AdvancingFrontNode( TriangulationPoint point )
|
||||||
|
{
|
||||||
|
this.point = point;
|
||||||
|
value = point.getX();
|
||||||
|
key = Double.valueOf( value ); // XXX: BST
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdvancingFrontNode getNext()
|
||||||
|
{
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdvancingFrontNode getPrevious()
|
||||||
|
{
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriangulationPoint getPoint()
|
||||||
|
{
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DelaunayTriangle getTriangle()
|
||||||
|
{
|
||||||
|
return triangle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasNext()
|
||||||
|
{
|
||||||
|
return next != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPrevious()
|
||||||
|
{
|
||||||
|
return prev != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
1290
src/main/java/org/poly2tri/triangulation/delaunay/sweep/DTSweep.java
Normal file
1290
src/main/java/org/poly2tri/triangulation/delaunay/sweep/DTSweep.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,103 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation.delaunay.sweep;
|
||||||
|
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.poly2tri.triangulation.TriangulationConstraint;
|
||||||
|
import org.poly2tri.triangulation.TriangulationPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Thomas <20>hl<68>n, thahlen@gmail.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DTSweepConstraint extends TriangulationConstraint
|
||||||
|
{
|
||||||
|
|
||||||
|
public TriangulationPoint p;
|
||||||
|
public TriangulationPoint q;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give two points in any order. Will always be ordered so
|
||||||
|
* that q.y > p.y and q.x > p.x if same y value
|
||||||
|
*
|
||||||
|
* @param p1
|
||||||
|
* @param p2
|
||||||
|
*/
|
||||||
|
public DTSweepConstraint( TriangulationPoint p1, TriangulationPoint p2 )
|
||||||
|
// throws DuplicatePointException
|
||||||
|
{
|
||||||
|
p = p1;
|
||||||
|
q = p2;
|
||||||
|
if( p1.getY() > p2.getY() )
|
||||||
|
{
|
||||||
|
q = p1;
|
||||||
|
p = p2;
|
||||||
|
}
|
||||||
|
else if( p1.getY() == p2.getY() )
|
||||||
|
{
|
||||||
|
if( p1.getX() > p2.getX() )
|
||||||
|
{
|
||||||
|
q = p1;
|
||||||
|
p = p2;
|
||||||
|
}
|
||||||
|
else if( p1.getX() == p2.getX() )
|
||||||
|
{
|
||||||
|
// throw new DuplicatePointException( p1 + "=" + p2 );
|
||||||
|
// return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
q.addEdge(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public TPoint intersect( TPoint a, TPoint b )
|
||||||
|
// {
|
||||||
|
// double pqx,pqy,bax,bay,t;
|
||||||
|
//
|
||||||
|
// pqx = p.getX()-q.getX();
|
||||||
|
// pqy = p.getY()-q.getY();
|
||||||
|
// t = pqy*(a.getX()-q.getX()) - pqx*(a.getY()-q.getY() );
|
||||||
|
// t /= pqx*(b.getY()-a.getY()) - pqy*(b.getX()-a.getX());
|
||||||
|
// bax = t*(b.getX()-a.getX()) + a.getX();
|
||||||
|
// bay = t*(b.getY()-a.getY()) + a.getY();
|
||||||
|
// return new TPoint( bax, bay );
|
||||||
|
// }
|
||||||
|
|
||||||
|
public TriangulationPoint getP()
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriangulationPoint getQ()
|
||||||
|
{
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,280 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation.delaunay.sweep;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Collections;
|
||||||
|
import org.poly2tri.triangulation.Triangulatable;
|
||||||
|
import org.poly2tri.triangulation.TriangulationAlgorithm;
|
||||||
|
import org.poly2tri.triangulation.TriangulationConstraint;
|
||||||
|
import org.poly2tri.triangulation.TriangulationContext;
|
||||||
|
import org.poly2tri.triangulation.TriangulationPoint;
|
||||||
|
import org.poly2tri.triangulation.delaunay.DelaunayTriangle;
|
||||||
|
import org.poly2tri.triangulation.point.TPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Thomas <20>hl<68>n, thahlen@gmail.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DTSweepContext extends TriangulationContext<DTSweepDebugContext>
|
||||||
|
{
|
||||||
|
|
||||||
|
// Inital triangle factor, seed triangle will extend 30% of
|
||||||
|
// PointSet width to both left and right.
|
||||||
|
private final float ALPHA = 0.3f;
|
||||||
|
|
||||||
|
/** Advancing front **/
|
||||||
|
protected AdvancingFront aFront;
|
||||||
|
/** head point used with advancing front */
|
||||||
|
private TriangulationPoint _head;
|
||||||
|
/** tail point used with advancing front */
|
||||||
|
private TriangulationPoint _tail;
|
||||||
|
protected Basin basin = new Basin();
|
||||||
|
protected EdgeEvent edgeEvent = new EdgeEvent();
|
||||||
|
|
||||||
|
private DTSweepPointComparator _comparator = new DTSweepPointComparator();
|
||||||
|
|
||||||
|
public DTSweepContext()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void isDebugEnabled( boolean b )
|
||||||
|
{
|
||||||
|
if( b )
|
||||||
|
{
|
||||||
|
if( _debug == null )
|
||||||
|
{
|
||||||
|
_debug = new DTSweepDebugContext(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_debugEnabled = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeFromList( DelaunayTriangle triangle )
|
||||||
|
{
|
||||||
|
_triList.remove( triangle );
|
||||||
|
// TODO: remove all neighbor pointers to this triangle
|
||||||
|
// for( int i=0; i<3; i++ )
|
||||||
|
// {
|
||||||
|
// if( triangle.neighbors[i] != null )
|
||||||
|
// {
|
||||||
|
// triangle.neighbors[i].clearNeighbor( triangle );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// triangle.clearNeighbors();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void meshClean(DelaunayTriangle triangle)
|
||||||
|
{
|
||||||
|
DelaunayTriangle t1,t2;
|
||||||
|
if( triangle != null )
|
||||||
|
{
|
||||||
|
ArrayDeque<DelaunayTriangle> deque = new ArrayDeque<DelaunayTriangle>();
|
||||||
|
deque.addFirst(triangle);
|
||||||
|
triangle.isInterior(true);
|
||||||
|
|
||||||
|
while( !deque.isEmpty() )
|
||||||
|
{
|
||||||
|
t1 = deque.removeFirst();
|
||||||
|
_triUnit.addTriangle( t1 );
|
||||||
|
for( int i=0; i<3; ++i )
|
||||||
|
{
|
||||||
|
if( !t1.cEdge[i] )
|
||||||
|
{
|
||||||
|
t2 = t1.neighbors[i];
|
||||||
|
if( t2 != null && !t2.isInterior() )
|
||||||
|
{
|
||||||
|
t2.isInterior(true);
|
||||||
|
deque.addLast(t2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
super.clear();
|
||||||
|
_triList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdvancingFront getAdvancingFront()
|
||||||
|
{
|
||||||
|
return aFront;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHead( TriangulationPoint p1 ) { _head = p1; }
|
||||||
|
public TriangulationPoint getHead() { return _head; }
|
||||||
|
|
||||||
|
public void setTail( TriangulationPoint p1 ) { _tail = p1; }
|
||||||
|
public TriangulationPoint getTail() { return _tail; }
|
||||||
|
|
||||||
|
public void addNode( AdvancingFrontNode node )
|
||||||
|
{
|
||||||
|
// System.out.println( "add:" + node.key + ":" + System.identityHashCode(node.key));
|
||||||
|
// m_nodeTree.put( node.getKey(), node );
|
||||||
|
aFront.addNode( node );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeNode( AdvancingFrontNode node )
|
||||||
|
{
|
||||||
|
// System.out.println( "remove:" + node.key + ":" + System.identityHashCode(node.key));
|
||||||
|
// m_nodeTree.delete( node.getKey() );
|
||||||
|
aFront.removeNode( node );
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdvancingFrontNode locateNode( TriangulationPoint point )
|
||||||
|
{
|
||||||
|
return aFront.locateNode( point );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createAdvancingFront()
|
||||||
|
{
|
||||||
|
AdvancingFrontNode head,tail,middle;
|
||||||
|
// Initial triangle
|
||||||
|
DelaunayTriangle iTriangle = new DelaunayTriangle( _points.get(0),
|
||||||
|
getTail(),
|
||||||
|
getHead() );
|
||||||
|
addToList( iTriangle );
|
||||||
|
|
||||||
|
head = new AdvancingFrontNode( iTriangle.points[1] );
|
||||||
|
head.triangle = iTriangle;
|
||||||
|
middle = new AdvancingFrontNode( iTriangle.points[0] );
|
||||||
|
middle.triangle = iTriangle;
|
||||||
|
tail = new AdvancingFrontNode( iTriangle.points[2] );
|
||||||
|
|
||||||
|
aFront = new AdvancingFront( head, tail );
|
||||||
|
aFront.addNode( middle );
|
||||||
|
|
||||||
|
// TODO: I think it would be more intuitive if head is middles next and not previous
|
||||||
|
// so swap head and tail
|
||||||
|
aFront.head.next = middle;
|
||||||
|
middle.next = aFront.tail;
|
||||||
|
middle.prev = aFront.head;
|
||||||
|
aFront.tail.prev = middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Basin
|
||||||
|
{
|
||||||
|
AdvancingFrontNode leftNode;
|
||||||
|
AdvancingFrontNode bottomNode;
|
||||||
|
AdvancingFrontNode rightNode;
|
||||||
|
public double width;
|
||||||
|
public boolean leftHighest;
|
||||||
|
}
|
||||||
|
|
||||||
|
class EdgeEvent
|
||||||
|
{
|
||||||
|
DTSweepConstraint constrainedEdge;
|
||||||
|
public boolean right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to map a node to all sides of this triangle that don't have
|
||||||
|
* a neighbor.
|
||||||
|
*
|
||||||
|
* @param t
|
||||||
|
*/
|
||||||
|
public void mapTriangleToNodes( DelaunayTriangle t )
|
||||||
|
{
|
||||||
|
AdvancingFrontNode n;
|
||||||
|
for( int i=0; i<3; i++ )
|
||||||
|
{
|
||||||
|
if( t.neighbors[i] == null )
|
||||||
|
{
|
||||||
|
n = aFront.locatePoint( t.pointCW( t.points[i] ) );
|
||||||
|
if( n != null )
|
||||||
|
{
|
||||||
|
n.triangle = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepareTriangulation( Triangulatable t )
|
||||||
|
{
|
||||||
|
super.prepareTriangulation( t );
|
||||||
|
|
||||||
|
double xmax, xmin;
|
||||||
|
double ymax, ymin;
|
||||||
|
|
||||||
|
xmax = xmin = _points.get(0).getX();
|
||||||
|
ymax = ymin = _points.get(0).getY();
|
||||||
|
// Calculate bounds. Should be combined with the sorting
|
||||||
|
for( TriangulationPoint p : _points )
|
||||||
|
{
|
||||||
|
if( p.getX() > xmax )
|
||||||
|
xmax = p.getX();
|
||||||
|
if( p.getX() < xmin )
|
||||||
|
xmin = p.getX();
|
||||||
|
if( p.getY() > ymax )
|
||||||
|
ymax = p.getY();
|
||||||
|
if( p.getY() < ymin )
|
||||||
|
ymin = p.getY();
|
||||||
|
}
|
||||||
|
|
||||||
|
double deltaX = ALPHA * ( xmax - xmin );
|
||||||
|
double deltaY = ALPHA * ( ymax - ymin );
|
||||||
|
TPoint p1 = new TPoint( xmax + deltaX, ymin - deltaY );
|
||||||
|
TPoint p2 = new TPoint( xmin - deltaX, ymin - deltaY );
|
||||||
|
|
||||||
|
setHead( p1 );
|
||||||
|
setTail( p2 );
|
||||||
|
|
||||||
|
// long time = System.nanoTime();
|
||||||
|
// Sort the points along y-axis
|
||||||
|
Collections.sort( _points, _comparator );
|
||||||
|
// logger.info( "Triangulation setup [{}ms]", ( System.nanoTime() - time ) / 1e6 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void finalizeTriangulation()
|
||||||
|
{
|
||||||
|
_triUnit.addTriangles( _triList );
|
||||||
|
_triList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TriangulationConstraint newConstraint( TriangulationPoint a, TriangulationPoint b )
|
||||||
|
{
|
||||||
|
return new DTSweepConstraint( a, b );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TriangulationAlgorithm algorithm()
|
||||||
|
{
|
||||||
|
return TriangulationAlgorithm.DTSweep;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package org.poly2tri.triangulation.delaunay.sweep;
|
||||||
|
|
||||||
|
import org.poly2tri.triangulation.TriangulationContext;
|
||||||
|
import org.poly2tri.triangulation.TriangulationDebugContext;
|
||||||
|
import org.poly2tri.triangulation.TriangulationPoint;
|
||||||
|
import org.poly2tri.triangulation.delaunay.DelaunayTriangle;
|
||||||
|
|
||||||
|
public class DTSweepDebugContext extends TriangulationDebugContext
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Fields used for visual representation of current triangulation
|
||||||
|
*/
|
||||||
|
protected DelaunayTriangle _primaryTriangle;
|
||||||
|
protected DelaunayTriangle _secondaryTriangle;
|
||||||
|
protected TriangulationPoint _activePoint;
|
||||||
|
protected AdvancingFrontNode _activeNode;
|
||||||
|
protected DTSweepConstraint _activeConstraint;
|
||||||
|
|
||||||
|
public DTSweepDebugContext( DTSweepContext tcx )
|
||||||
|
{
|
||||||
|
super( tcx );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDebugContext()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// private Tuple2<TPoint,Double> m_circumCircle = new Tuple2<TPoint,Double>( new TPoint(), new Double(0) );
|
||||||
|
// public Tuple2<TPoint,Double> getCircumCircle() { return m_circumCircle; }
|
||||||
|
public DelaunayTriangle getPrimaryTriangle()
|
||||||
|
{
|
||||||
|
return _primaryTriangle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DelaunayTriangle getSecondaryTriangle()
|
||||||
|
{
|
||||||
|
return _secondaryTriangle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdvancingFrontNode getActiveNode()
|
||||||
|
{
|
||||||
|
return _activeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DTSweepConstraint getActiveConstraint()
|
||||||
|
{
|
||||||
|
return _activeConstraint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriangulationPoint getActivePoint()
|
||||||
|
{
|
||||||
|
return _activePoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrimaryTriangle( DelaunayTriangle triangle )
|
||||||
|
{
|
||||||
|
_primaryTriangle = triangle;
|
||||||
|
_tcx.update("setPrimaryTriangle");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecondaryTriangle( DelaunayTriangle triangle )
|
||||||
|
{
|
||||||
|
_secondaryTriangle = triangle;
|
||||||
|
_tcx.update("setSecondaryTriangle");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActivePoint( TriangulationPoint point )
|
||||||
|
{
|
||||||
|
_activePoint = point;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActiveConstraint( DTSweepConstraint e )
|
||||||
|
{
|
||||||
|
_activeConstraint = e;
|
||||||
|
_tcx.update("setWorkingSegment");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActiveNode( AdvancingFrontNode node )
|
||||||
|
{
|
||||||
|
_activeNode = node;
|
||||||
|
_tcx.update("setWorkingNode");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
_primaryTriangle = null;
|
||||||
|
_secondaryTriangle = null;
|
||||||
|
_activePoint = null;
|
||||||
|
_activeNode = null;
|
||||||
|
_activeConstraint = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void setWorkingCircumCircle( TPoint point, TPoint point2, TPoint point3 )
|
||||||
|
// {
|
||||||
|
// double dx,dy;
|
||||||
|
//
|
||||||
|
// CircleXY.circumCenter( point, point2, point3, m_circumCircle.a );
|
||||||
|
// dx = m_circumCircle.a.getX()-point.getX();
|
||||||
|
// dy = m_circumCircle.a.getY()-point.getY();
|
||||||
|
// m_circumCircle.b = Double.valueOf( Math.sqrt( dx*dx + dy*dy ) );
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package org.poly2tri.triangulation.delaunay.sweep;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import org.poly2tri.triangulation.TriangulationPoint;
|
||||||
|
|
||||||
|
public class DTSweepPointComparator implements Comparator<TriangulationPoint>
|
||||||
|
{
|
||||||
|
public int compare( TriangulationPoint p1, TriangulationPoint p2 )
|
||||||
|
{
|
||||||
|
if(p1.getY() < p2.getY() )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if( p1.getY() > p2.getY())
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(p1.getX() < p2.getX())
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if( p1.getX() > p2.getX() )
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package org.poly2tri.triangulation.delaunay.sweep;
|
||||||
|
|
||||||
|
public class PointOnEdgeException extends RuntimeException
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public PointOnEdgeException( String msg )
|
||||||
|
{
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation.point;
|
||||||
|
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
|
import org.poly2tri.triangulation.TriangulationPoint;
|
||||||
|
|
||||||
|
|
||||||
|
public class FloatBufferPoint extends TriangulationPoint
|
||||||
|
{
|
||||||
|
private final FloatBuffer _fb;
|
||||||
|
private final int _ix,_iy,_iz;
|
||||||
|
|
||||||
|
public FloatBufferPoint( FloatBuffer fb, int index )
|
||||||
|
{
|
||||||
|
_fb = fb;
|
||||||
|
_ix = index;
|
||||||
|
_iy = index+1;
|
||||||
|
_iz = index+2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final double getX()
|
||||||
|
{
|
||||||
|
return _fb.get( _ix );
|
||||||
|
}
|
||||||
|
public final double getY()
|
||||||
|
{
|
||||||
|
return _fb.get( _iy );
|
||||||
|
}
|
||||||
|
public final double getZ()
|
||||||
|
{
|
||||||
|
return _fb.get( _iz );
|
||||||
|
}
|
||||||
|
|
||||||
|
public final float getXf()
|
||||||
|
{
|
||||||
|
return _fb.get( _ix );
|
||||||
|
}
|
||||||
|
public final float getYf()
|
||||||
|
{
|
||||||
|
return _fb.get( _iy );
|
||||||
|
}
|
||||||
|
public final float getZf()
|
||||||
|
{
|
||||||
|
return _fb.get( _iz );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set( double x, double y, double z )
|
||||||
|
{
|
||||||
|
_fb.put( _ix, (float)x );
|
||||||
|
_fb.put( _iy, (float)y );
|
||||||
|
_fb.put( _iz, (float)z );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TriangulationPoint[] toPoints( FloatBuffer fb )
|
||||||
|
{
|
||||||
|
FloatBufferPoint[] points = new FloatBufferPoint[fb.limit()/3];
|
||||||
|
for( int i=0,j=0; i<points.length; i++, j+=3 )
|
||||||
|
{
|
||||||
|
points[i] = new FloatBufferPoint(fb, j);
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
}
|
||||||
69
src/main/java/org/poly2tri/triangulation/point/TPoint.java
Normal file
69
src/main/java/org/poly2tri/triangulation/point/TPoint.java
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation.point;
|
||||||
|
|
||||||
|
import org.poly2tri.triangulation.TriangulationPoint;
|
||||||
|
|
||||||
|
public class TPoint extends TriangulationPoint
|
||||||
|
{
|
||||||
|
private double _x;
|
||||||
|
private double _y;
|
||||||
|
private double _z;
|
||||||
|
|
||||||
|
public TPoint( double x, double y )
|
||||||
|
{
|
||||||
|
this( x, y, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public TPoint( double x, double y, double z )
|
||||||
|
{
|
||||||
|
_x = x;
|
||||||
|
_y = y;
|
||||||
|
_z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX() { return _x; }
|
||||||
|
public double getY() { return _y; }
|
||||||
|
public double getZ() { return _z; }
|
||||||
|
|
||||||
|
public float getXf() { return (float)_x; }
|
||||||
|
public float getYf() { return (float)_y; }
|
||||||
|
public float getZf() { return (float)_z; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set( double x, double y, double z )
|
||||||
|
{
|
||||||
|
_x = x;
|
||||||
|
_y = y;
|
||||||
|
_z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation.sets;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.poly2tri.triangulation.TriangulationContext;
|
||||||
|
import org.poly2tri.triangulation.TriangulationMode;
|
||||||
|
import org.poly2tri.triangulation.TriangulationPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends the PointSet by adding some Constraints on how it will be triangulated<br>
|
||||||
|
* A constraint defines an edge between two points in the set, these edges can not
|
||||||
|
* be crossed. They will be enforced triangle edges after a triangulation.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author Thomas <20>hl<68>n, thahlen@gmail.com
|
||||||
|
*/
|
||||||
|
public class ConstrainedPointSet extends PointSet
|
||||||
|
{
|
||||||
|
int[] _index;
|
||||||
|
List<TriangulationPoint> _constrainedPointList = null;
|
||||||
|
|
||||||
|
public ConstrainedPointSet( List<TriangulationPoint> points, int[] index )
|
||||||
|
{
|
||||||
|
super( points );
|
||||||
|
_index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param points - A list of all points in PointSet
|
||||||
|
* @param constraints - Pairs of two points defining a constraint, all points <b>must</b> be part of given PointSet!
|
||||||
|
*/
|
||||||
|
public ConstrainedPointSet( List<TriangulationPoint> points, List<TriangulationPoint> constraints )
|
||||||
|
{
|
||||||
|
super( points );
|
||||||
|
_constrainedPointList = new ArrayList<TriangulationPoint>();
|
||||||
|
_constrainedPointList.addAll(constraints);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TriangulationMode getTriangulationMode()
|
||||||
|
{
|
||||||
|
return TriangulationMode.CONSTRAINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] getEdgeIndex()
|
||||||
|
{
|
||||||
|
return _index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void prepareTriangulation( TriangulationContext tcx )
|
||||||
|
{
|
||||||
|
super.prepareTriangulation( tcx );
|
||||||
|
if( _constrainedPointList != null )
|
||||||
|
{
|
||||||
|
TriangulationPoint p1,p2;
|
||||||
|
Iterator iterator = _constrainedPointList.iterator();
|
||||||
|
while(iterator.hasNext())
|
||||||
|
{
|
||||||
|
p1 = (TriangulationPoint)iterator.next();
|
||||||
|
p2 = (TriangulationPoint)iterator.next();
|
||||||
|
tcx.newConstraint(p1,p2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( int i = 0; i < _index.length; i+=2 )
|
||||||
|
{
|
||||||
|
// XXX: must change!!
|
||||||
|
tcx.newConstraint( _points.get( _index[i] ), _points.get( _index[i+1] ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: TO BE IMPLEMENTED!
|
||||||
|
* Peforms a validation on given input<br>
|
||||||
|
* 1. Check's if there any constraint edges are crossing or collinear<br>
|
||||||
|
* 2.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isValid()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
95
src/main/java/org/poly2tri/triangulation/sets/PointSet.java
Normal file
95
src/main/java/org/poly2tri/triangulation/sets/PointSet.java
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation.sets;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.poly2tri.triangulation.Triangulatable;
|
||||||
|
import org.poly2tri.triangulation.TriangulationContext;
|
||||||
|
import org.poly2tri.triangulation.TriangulationMode;
|
||||||
|
import org.poly2tri.triangulation.TriangulationPoint;
|
||||||
|
import org.poly2tri.triangulation.delaunay.DelaunayTriangle;
|
||||||
|
|
||||||
|
public class PointSet implements Triangulatable
|
||||||
|
{
|
||||||
|
List<TriangulationPoint> _points;
|
||||||
|
List<DelaunayTriangle> _triangles;
|
||||||
|
|
||||||
|
public PointSet( List<TriangulationPoint> points )
|
||||||
|
{
|
||||||
|
_points = new ArrayList<TriangulationPoint>();
|
||||||
|
_points.addAll( points );
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriangulationMode getTriangulationMode()
|
||||||
|
{
|
||||||
|
return TriangulationMode.UNCONSTRAINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TriangulationPoint> getPoints()
|
||||||
|
{
|
||||||
|
return _points;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DelaunayTriangle> getTriangles()
|
||||||
|
{
|
||||||
|
return _triangles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTriangle( DelaunayTriangle t )
|
||||||
|
{
|
||||||
|
_triangles.add( t );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTriangles( List<DelaunayTriangle> list )
|
||||||
|
{
|
||||||
|
_triangles.addAll( list );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearTriangulation()
|
||||||
|
{
|
||||||
|
_triangles.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void prepareTriangulation( TriangulationContext<?> tcx )
|
||||||
|
{
|
||||||
|
if( _triangles == null )
|
||||||
|
{
|
||||||
|
_triangles = new ArrayList<DelaunayTriangle>( _points.size() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_triangles.clear();
|
||||||
|
}
|
||||||
|
tcx.addPoints( _points );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package org.poly2tri.triangulation.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.poly2tri.triangulation.TriangulationPoint;
|
||||||
|
import org.poly2tri.triangulation.point.TPoint;
|
||||||
|
|
||||||
|
public class PointGenerator
|
||||||
|
{
|
||||||
|
public static List<TriangulationPoint> uniformDistribution( int n, double scale )
|
||||||
|
{
|
||||||
|
ArrayList<TriangulationPoint> points = new ArrayList<TriangulationPoint>();
|
||||||
|
for( int i=0; i<n; i++ )
|
||||||
|
{
|
||||||
|
points.add( new TPoint( scale*(0.5 - Math.random()), scale*(0.5 - Math.random()) ) );
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<TriangulationPoint> uniformGrid( int n, double scale )
|
||||||
|
{
|
||||||
|
double x=0;
|
||||||
|
double size = scale/n;
|
||||||
|
double halfScale = 0.5*scale;
|
||||||
|
|
||||||
|
ArrayList<TriangulationPoint> points = new ArrayList<TriangulationPoint>();
|
||||||
|
for( int i=0; i<n+1; i++ )
|
||||||
|
{
|
||||||
|
x = halfScale - i*size;
|
||||||
|
for( int j=0; j<n+1; j++ )
|
||||||
|
{
|
||||||
|
points.add( new TPoint( x, halfScale - j*size ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation.util;
|
||||||
|
|
||||||
|
import org.poly2tri.geometry.polygon.Polygon;
|
||||||
|
import org.poly2tri.geometry.polygon.PolygonPoint;
|
||||||
|
|
||||||
|
public class PolygonGenerator
|
||||||
|
{
|
||||||
|
private static final double PI_2 = 2.0*Math.PI;
|
||||||
|
|
||||||
|
public static Polygon RandomCircleSweep( double scale, int vertexCount )
|
||||||
|
{
|
||||||
|
PolygonPoint point;
|
||||||
|
PolygonPoint[] points;
|
||||||
|
double radius = scale/4;
|
||||||
|
|
||||||
|
points = new PolygonPoint[vertexCount];
|
||||||
|
for(int i=0; i<vertexCount; i++)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if( i%250 == 0 )
|
||||||
|
{
|
||||||
|
radius += scale/2*(0.5 - Math.random());
|
||||||
|
}
|
||||||
|
else if( i%50 == 0 )
|
||||||
|
{
|
||||||
|
radius += scale/5*(0.5 - Math.random());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
radius += 25*scale/vertexCount*(0.5 - Math.random());
|
||||||
|
}
|
||||||
|
radius = radius > scale/2 ? scale/2 : radius;
|
||||||
|
radius = radius < scale/10 ? scale/10 : radius;
|
||||||
|
} while( radius < scale/10 || radius > scale/2 );
|
||||||
|
point = new PolygonPoint( radius*Math.cos( (PI_2*i)/vertexCount ),
|
||||||
|
radius*Math.sin( (PI_2*i)/vertexCount ) );
|
||||||
|
points[i] = point;
|
||||||
|
}
|
||||||
|
return new Polygon( points );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Polygon RandomCircleSweep2( double scale, int vertexCount )
|
||||||
|
{
|
||||||
|
PolygonPoint point;
|
||||||
|
PolygonPoint[] points;
|
||||||
|
double radius = scale/4;
|
||||||
|
|
||||||
|
points = new PolygonPoint[vertexCount];
|
||||||
|
for(int i=0; i<vertexCount; i++)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
radius += scale/5*(0.5 - Math.random());
|
||||||
|
radius = radius > scale/2 ? scale/2 : radius;
|
||||||
|
radius = radius < scale/10 ? scale/10 : radius;
|
||||||
|
} while( radius < scale/10 || radius > scale/2 );
|
||||||
|
point = new PolygonPoint( radius*Math.cos( (PI_2*i)/vertexCount ),
|
||||||
|
radius*Math.sin( (PI_2*i)/vertexCount ) );
|
||||||
|
points[i] = point;
|
||||||
|
}
|
||||||
|
return new Polygon( points );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.poly2tri.triangulation.util;
|
||||||
|
|
||||||
|
import org.poly2tri.geometry.polygon.Polygon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use a QuadTree traversal to add steiner points
|
||||||
|
* inside the polygon that needs refinement
|
||||||
|
*
|
||||||
|
* @author thahlen@gmail.com
|
||||||
|
*/
|
||||||
|
public class QuadTreeRefinement
|
||||||
|
{
|
||||||
|
public static final void refine( Polygon p, int depth )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
43
src/main/java/org/poly2tri/triangulation/util/Tuple2.java
Normal file
43
src/main/java/org/poly2tri/triangulation/util/Tuple2.java
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation.util;
|
||||||
|
|
||||||
|
public class Tuple2<A,B>
|
||||||
|
{
|
||||||
|
public A a;
|
||||||
|
public B b;
|
||||||
|
|
||||||
|
public Tuple2(A a,B b)
|
||||||
|
{
|
||||||
|
this.a = a;
|
||||||
|
this.b = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/main/java/org/poly2tri/triangulation/util/Tuple3.java
Normal file
45
src/main/java/org/poly2tri/triangulation/util/Tuple3.java
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/* Poly2Tri
|
||||||
|
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||||
|
* http://code.google.com/p/poly2tri/
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.poly2tri.triangulation.util;
|
||||||
|
|
||||||
|
public class Tuple3<A,B,C>
|
||||||
|
{
|
||||||
|
public A a;
|
||||||
|
public B b;
|
||||||
|
public C c;
|
||||||
|
|
||||||
|
public Tuple3(A a,B b,C c)
|
||||||
|
{
|
||||||
|
this.a = a;
|
||||||
|
this.b = b;
|
||||||
|
this.c = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user